home *** CD-ROM | disk | FTP | other *** search
/ Computer Shopper 253 / Issue 253 - March 2009 - DPCS0309DVD.ISO / Toolkit / Internet / WinHTTrack / httrack-3.43.exe / {app} / src / htscoremain.c < prev    next >
Encoding:
C/C++ Source or Header  |  2008-09-28  |  90.7 KB  |  2,339 lines

  1. /* ------------------------------------------------------------ */
  2. /*
  3. HTTrack Website Copier, Offline Browser for Windows and Unix
  4. Copyright (C) Xavier Roche and other contributors
  5.  
  6. This program is free software; you can redistribute it and/or
  7. modify it under the terms of the GNU General Public License
  8. as published by the Free Software Foundation; either version 2
  9. of the License, or any later version.
  10.  
  11. This program is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with this program; if not, write to the Free Software
  18. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  19.  
  20.  
  21. Important notes:
  22.  
  23. - We hereby ask people using this source NOT to use it in purpose of grabbing
  24. emails addresses, or collecting any other private information on persons.
  25. This would disgrace our work, and spoil the many hours we spent on it.
  26.  
  27.  
  28. Please visit our Website: http://www.httrack.com
  29. */
  30.  
  31.  
  32. /* ------------------------------------------------------------ */
  33. /* File: opt->c subroutines:                                 */
  34. /*       main routine (first called)                            */
  35. /* Author: Xavier Roche                                         */
  36. /* ------------------------------------------------------------ */
  37.  
  38. /* Internal engine bytecode */
  39. #define HTS_INTERNAL_BYTECODE
  40.  
  41. #include "htscoremain.h"
  42.  
  43. #include "htsglobal.h"
  44. #include "htscore.h"
  45. #include "htsdefines.h"
  46. #include "htsalias.h"
  47. #include "htswrap.h"
  48. #include "htsmodules.h"
  49. #include "htszlib.h"
  50.  
  51. #include <ctype.h>
  52. #if USE_BEGINTHREAD
  53. #ifdef _WIN32
  54. #include <process.h>
  55. #endif
  56. #endif
  57. #ifdef _WIN32
  58. #else
  59. #ifndef HTS_DO_NOT_USE_UID
  60. /* setuid */
  61. #include <pwd.h>
  62. #ifdef HAVE_UNISTD_H
  63. #include <unistd.h>
  64. #endif
  65. #endif
  66. #endif
  67.  
  68. /* Resolver */
  69. extern int IPV6_resolver;
  70.  
  71.  
  72. // Add a command in the argc/argv
  73. #define cmdl_add(token,argc,argv,buff,ptr) \
  74.   argv[argc]=(buff+ptr); \
  75.   strcpybuff(argv[argc],token); \
  76.   ptr += (int) (strlen(argv[argc])+2); \
  77.   argc++
  78.  
  79. // Insert a command in the argc/argv
  80. #define cmdl_ins(token,argc,argv,buff,ptr) \
  81.   { \
  82.   int i; \
  83.   for(i=argc;i>0;i--)\
  84.   argv[i]=argv[i-1];\
  85.   } \
  86.   argv[0]=(buff+ptr); \
  87.   strcpybuff(argv[0],token); \
  88.   ptr += (int) (strlen(argv[0])+2); \
  89.   argc++
  90.  
  91. #define htsmain_free() do { if (url != NULL) { free(url); } } while(0)
  92.  
  93. #define ensureUrlCapacity(url, urlsize, size) do { \
  94.   if (urlsize < size || url == NULL) { \
  95.     urlsize = size; \
  96.     if (url == NULL) { \
  97.       url = (char*) malloct(urlsize); \
  98.       if (url != NULL) url[0]='\0'; \
  99.     } else { \
  100.       url = (char*) realloct(url, urlsize); \
  101.     } \
  102.     if (url == NULL) { \
  103.       HTS_PANIC_PRINTF("* memory exhausted"); \
  104.       htsmain_free(); \
  105.       return -1; \
  106.     } \
  107.   } \
  108. } while(0)
  109.  
  110. HTSEXT_API int hts_main(int argc, char **argv)
  111. {
  112.   httrackp *opt = hts_create_opt();
  113.     int ret = hts_main2(argc, argv, opt);
  114.     hts_free_opt(opt);
  115.     return ret;
  116. }
  117.  
  118. // Main, rΘcupΦre les paramΦtres et appelle le robot
  119. HTSEXT_API int hts_main2(int argc, char **argv, httrackp *opt) {
  120.   char** x_argv=NULL;     // Patch pour argv et argc: en cas de rΘcupΘration de ligne de commande
  121.   char* x_argvblk=NULL;   // (reprise ou update)
  122.   int   x_ptr=0;          // offset
  123.   //
  124.   int argv_url=-1;           // ==0 : utiliser cache et doit.log
  125.   char* argv_firsturl=NULL;  // utilisΘ pour nommage par dΘfaut
  126.   char* url = NULL;          // URLS sΘparΘes par un espace
  127.   int   url_sz = 65535;
  128.   //char url[65536];         // URLS sΘparΘes par un espace
  129.   // the parametres
  130.   int httrack_logmode=3;   // ONE log file
  131.   int recuperer=0;         // rΘcupΘrer un plantage (n'arrive jamais, α supprimer)
  132. #ifndef _WIN32
  133. #ifndef HTS_DO_NOT_USE_UID
  134.   int switch_uid=-1,switch_gid=-1;      /* setuid/setgid */
  135. #endif
  136.   int switch_chroot=0;                  /* chroot ? */
  137. #endif
  138.   //
  139.   ensureUrlCapacity(url, url_sz, 65536);
  140.  
  141.     // Create options
  142.     _DEBUG_HEAD=0;            // pas de debuggage en tΩtes
  143.  
  144.   /* command max-size check (3.43 ; 3.42-4) */
  145.   {
  146.     int i;
  147.     for(i = 0 ; i < argc ; i++) {
  148.       if (strlen(argv[i]) >= HTS_CDLMAXSIZE) {
  149.         HTS_PANIC_PRINTF("argument too long");
  150.         htsmain_free();
  151.         return -1;
  152.       }
  153.     }
  154.   }
  155.  
  156.   /* Init root dir */
  157.   hts_rootdir(argv[0]);
  158.  
  159. #ifdef _WIN32
  160. #else
  161.   /* Terminal is a tty, may ask questions and display funny information */
  162.   if (isatty(1)) {
  163.     opt->quiet=0;
  164.     opt->verbosedisplay=1;
  165.   }
  166.   /* Not a tty, no stdin input or funny output! */
  167.   else {
  168.     opt->quiet=1;
  169.     opt->verbosedisplay=0;
  170.   }
  171. #endif
  172.  
  173.   // Binary program path?
  174. #ifndef HTS_HTTRACKDIR
  175.   {
  176.       char catbuff[CATBUFF_SIZE];
  177.     char* path=fslash(catbuff,argv[0]);
  178.     char* a;
  179.     if ((a=strrchr(path,'/'))) {
  180.       StringCopyN(opt->path_bin,argv[0],a - path);
  181.     }
  182.   }
  183. #else
  184.   StringCopy(opt->path_bin, HTS_HTTRACKDIR);
  185. #endif
  186.  
  187.   /* filter CR, LF, TAB.. */
  188.   {
  189.     int na;
  190.     for(na=1;na<argc;na++) {
  191.       char* a;
  192.       while( (a=strchr(argv[na],'\x0d')) ) *a=' ';
  193.       while( (a=strchr(argv[na],'\x0a')) ) *a=' ';
  194.       while( (a=strchr(argv[na],9)) )      *a=' ';
  195.       /* equivalent to "empty parameter" */
  196.       if ((strcmp(argv[na],HTS_NOPARAM)==0) || (strcmp(argv[na],HTS_NOPARAM2)==0))        // (none)
  197.         strcpybuff(argv[na],"\"\"");
  198.       if (strncmp(argv[na],"-&",2)==0)
  199.         argv[na][1]='%';
  200.     }
  201.   }
  202.  
  203.   /* create x_argvblk buffer for transformed command line */
  204.   {
  205.     int current_size=0;
  206.     int size;
  207.     int na;
  208.     for(na=0;na<argc;na++)
  209.       current_size += (int) (strlen(argv[na]) + 1);
  210.     if ((size=fsize("config"))>0)
  211.       current_size += size;
  212.     x_argvblk=(char*) malloct(current_size+32768);
  213.     if (x_argvblk == NULL) {
  214.       HTS_PANIC_PRINTF("Error, not enough memory");
  215.       htsmain_free();
  216.       return -1;
  217.     }
  218.     x_argvblk[0]='\0';
  219.     x_ptr=0;
  220.  
  221.     /* Create argv */
  222.     x_argv = (char**) malloct(sizeof(char*) * ( argc + 1024 ));
  223.   }
  224.  
  225.   /* Create new argc/argv, replace alias, count URLs, treat -h, -q, -i */
  226.   {
  227.     char BIGSTK _tmp_argv[2][HTS_CDLMAXSIZE];
  228.     char BIGSTK tmp_error[HTS_CDLMAXSIZE];
  229.     char* tmp_argv[2];
  230.     int tmp_argc;
  231.     int x_argc=0;
  232.     int na;
  233.     tmp_argv[0]=_tmp_argv[0];
  234.     tmp_argv[1]=_tmp_argv[1];
  235.     //
  236.     argv_url=0;       /* pour comptage */
  237.     //
  238.     cmdl_add(argv[0],x_argc,x_argv,x_argvblk,x_ptr);
  239.     na=1;             /* commencer aprΦs nom_prg */
  240.     while(na<argc) {
  241.       int result=1;
  242.       tmp_argv[0][0]=tmp_argv[1][0]='\0';
  243.  
  244.       /* VΘrifier argv[] non vide */
  245.       if (strnotempty(argv[na])) {
  246.         
  247.         /* VΘrifier Commande (alias) */
  248.         result=optalias_check(argc,(const char * const *)argv,na,
  249.           &tmp_argc,(char**)tmp_argv,tmp_error);
  250.         if (!result) {
  251.           HTS_PANIC_PRINTF(tmp_error);
  252.           htsmain_free();
  253.           return -1;
  254.         }
  255.         
  256.         /* Copier */
  257.         cmdl_add(tmp_argv[0],x_argc,x_argv,x_argvblk,x_ptr);
  258.         if (tmp_argc > 1) {
  259.           cmdl_add(tmp_argv[1],x_argc,x_argv,x_argvblk,x_ptr);
  260.         }
  261.         
  262.         /* Compter URLs et dΘtecter -i,-q.. */
  263.         if (tmp_argc == 1) {           /* pas -P & co */
  264.           if (!cmdl_opt(tmp_argv[0])) {   /* pas -c0 & co */
  265.             if (argv_url<0) argv_url=0;   // -1==force -> 1=one url already detected, wipe all previous options
  266.             //if (argv_url>=0) {
  267.             argv_url++;
  268.             if (!argv_firsturl)
  269.               argv_firsturl=x_argv[x_argc-1];
  270.             //}
  271.           } else {
  272.             if (strcmp(tmp_argv[0],"-h")==0) {
  273.               help(argv[0],!opt->quiet);
  274.               htsmain_free();
  275.               return 0;
  276.             } else if (strcmp(tmp_argv[0],"-#h")==0) {
  277.               printf("HTTrack version "HTTRACK_VERSION"%s\n", hts_get_version_info(opt));
  278.               return 0;
  279.             } else {
  280.               if (strncmp(tmp_argv[0],"--",2)) {   /* pas */
  281.                 if ((strchr(tmp_argv[0],'q')!=NULL))
  282.                   opt->quiet=1;    // ne pas poser de questions! (nohup par exemple)
  283.                 if ((strchr(tmp_argv[0],'i')!=NULL)) {  // doit.log!
  284.                   argv_url=-1;        /* forcer */
  285.                   opt->quiet=1;
  286.                 }
  287.               } else if (strcmp(tmp_argv[0] + 2,"quiet") == 0) {
  288.                 opt->quiet=1;    // ne pas poser de questions! (nohup par exemple)
  289.               } else if (strcmp(tmp_argv[0] + 2,"continue") == 0) {
  290.                 argv_url=-1;        /* forcer */
  291.                 opt->quiet=1;
  292.               }
  293.             }
  294.           }
  295.         } else if (tmp_argc == 2) {
  296.           if ((strcmp(tmp_argv[0],"-%L")==0)) {  // liste d'URLs
  297.             if (argv_url<0) argv_url=0;   // -1==force -> 1=one url already detected, wipe all previous options
  298.             //if (argv_url>=0)
  299.             argv_url++;        /* forcer */
  300.           }
  301.         }
  302.       }
  303.  
  304.       na+=result;
  305.     }
  306.     if (argv_url<0)
  307.       argv_url=0;
  308.  
  309.     /* Nouveaux argc et argv */
  310.     argv=x_argv;
  311.     argc=x_argc;
  312.   }
  313.  
  314.   // Option O and includerc
  315.   { 
  316.     int loops=0;
  317.     while (loops<2) {
  318.       char* com;
  319.       int na;
  320.       
  321.       for(na=1;na<argc;na++) {
  322.         
  323.         if (argv[na][0]=='"') {
  324.           char BIGSTK tempo[HTS_CDLMAXSIZE];
  325.           strcpybuff(tempo,argv[na]+1);
  326.           if (tempo[strlen(tempo)-1]!='"') {
  327.             char BIGSTK s[HTS_CDLMAXSIZE];
  328.             sprintf(s,"Missing quote in %s",argv[na]);
  329.             HTS_PANIC_PRINTF(s);
  330.             htsmain_free();
  331.             return -1;
  332.           }
  333.           tempo[strlen(tempo)-1]='\0';
  334.           strcpybuff(argv[na],tempo);
  335.         }
  336.         
  337.         if (cmdl_opt(argv[na])) { // option
  338.           com=argv[na]+1;
  339.           
  340.           while(*com) {
  341.             switch(*com) {
  342.             case 'O':    // output path
  343.               if ((na+1>=argc) || (argv[na+1][0]=='-')) {
  344.                 HTS_PANIC_PRINTF("Option O needs to be followed by a blank space, and a path (or path,path)");
  345.                 printf("Example: -O /binary/\n");
  346.                 printf("Example: -O /binary/,/log/\n");
  347.                 htsmain_free();
  348.                 return -1;
  349.               } else {
  350.                                 int i, j;
  351.                                 int inQuote;
  352.                                 String *path;
  353.                                 int noDbl = 0;
  354.                                 if (com[1] == '1') {            /* only 1 arg */
  355.                                     com++;
  356.                                     noDbl = 1;
  357.                                 }
  358.                 na++;
  359.                                 StringClear(opt->path_html);
  360.                 StringClear(opt->path_log);
  361.                                 for(i = 0, j = 0, inQuote = 0, path = &opt->path_html ; argv[na][i] != 0 ; i++) {
  362.                                     if (argv[na][i] == '"') {
  363.                                         if (inQuote)
  364.                                             inQuote = 0;
  365.                                         else
  366.                                             inQuote = 1;
  367.                                     } else if (!inQuote && !noDbl && argv[na][i] == ',') {
  368.                     //StringAddchar(path, '\0');
  369.                                         j = 0;
  370.                                         path = &opt->path_log;
  371.                                     } else {
  372.                     StringAddchar(*path, argv[na][i]);
  373.                                         //path[j++] = argv[na][i];
  374.                                     }
  375.                                 }
  376.                                 //path[j++] = '\0';
  377.                                 if (StringLength(opt->path_log) == 0) {
  378.                                     StringCopyS(opt->path_log, opt->path_html);
  379.                                 }
  380.  
  381.                 check_path(&opt->path_log, argv_firsturl);
  382.                 if (check_path(&opt->path_html, argv_firsturl)) {
  383.                   opt->dir_topindex=1;     // rebuilt top index
  384.                 }
  385.                 
  386.                 //printf("-->%s\n%s\n",StringBuff(opt->path_html),StringBuff(opt->path_log));                
  387.               }
  388.               break;
  389.             }  // switch
  390.             com++;    
  391.           }  // while
  392.           
  393.         }  // arg
  394.         
  395.       }  // for
  396.      
  397.          /* if doit.log exists, or if new URL(s) defined, 
  398.       then DO NOT load standard config files */
  399.       /* (config files are added in doit.log) */
  400. #if DEBUG_STEPS
  401.       printf("Loading httrackrc/doit.log\n");
  402. #endif
  403.       /* recreate a doit.log (no old doit.log or new URLs (and parameters)) */
  404.       if ((strnotempty(StringBuff(opt->path_log))) || (strnotempty(StringBuff(opt->path_html))))
  405.         loops++;      // do not loop once again and do not include rc file (O option exists)
  406.       else {
  407.         if ( (!fexist(fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-cache/doit.log"))) || (argv_url>0) ) {
  408.           if (!optinclude_file(fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),HTS_HTTRACKRC),&argc,argv,x_argvblk,&x_ptr))
  409.             if (!optinclude_file(HTS_HTTRACKRC,&argc,argv,x_argvblk,&x_ptr)) {
  410.               if (!optinclude_file(fconcat(OPT_GET_BUFF(opt), hts_gethome(),"/"HTS_HTTRACKRC),&argc,argv,x_argvblk,&x_ptr)) {
  411. #ifdef HTS_HTTRACKCNF
  412.                 optinclude_file(HTS_HTTRACKCNF,&argc,argv,x_argvblk,&x_ptr);
  413. #endif
  414.               }
  415.             }
  416.         } else
  417.           loops++;      // do not loop once again
  418.       }
  419.  
  420.       loops++;
  421.    } // while
  422.  
  423.   }  // traiter -O
  424.  
  425.   /* load doit.log and insert in current command line */
  426.   if ( fexist(fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-cache/doit.log")) && (argv_url<=0) ) {
  427.     FILE* fp=fopen(fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-cache/doit.log"),"rb");
  428.     if (fp) {
  429.       int insert_after=1;     /* insΘrer aprΦs nom au dΘbut */
  430.       //
  431.       char BIGSTK buff[8192];
  432.       char *p,*lastp;
  433.       linput(fp,buff,8000);
  434.       fclose(fp); fp=NULL;
  435.       p=buff;
  436.       do {
  437.         int insert_after_argc;
  438.         // read next
  439.         lastp=p;
  440.         if (p) {
  441.           p=next_token(p,1);
  442.           if (p) {
  443.             *p=0;    // null
  444.             p++;
  445.           }
  446.         }
  447.  
  448.         /* Insert parameters BUT so that they can be in the same order */
  449.         if (lastp) {
  450.           if (strnotempty(lastp)) {
  451.             insert_after_argc=argc-insert_after;
  452.             cmdl_ins(lastp,insert_after_argc,(argv+insert_after),x_argvblk,x_ptr);
  453.             argc=insert_after_argc+insert_after;
  454.             insert_after++;
  455.           }
  456.         }
  457.       } while(lastp!=NULL);
  458.       //fclose(fp);
  459.     }
  460.   }
  461.  
  462.  
  463.   // Existence d'un cache - pas de new mais un old.. renommer
  464. #if DEBUG_STEPS
  465.   printf("Checking cache\n");
  466. #endif
  467.   if (!fexist(fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-cache/new.zip"))) {
  468.     if ( fexist(fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-cache/old.zip")) ) {
  469.       rename(fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-cache/old.zip"),fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-cache/new.zip"));
  470.     }
  471.   } else if ( (!fexist(fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-cache/new.dat"))) || (!fexist(fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-cache/new.ndx"))) ) {
  472.     if ( (fexist(fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-cache/old.dat"))) && (fexist(fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-cache/old.ndx"))) ) {
  473.       remove(fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-cache/new.dat"));
  474.       remove(fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-cache/new.ndx"));
  475.       //remove(fconcat(StringBuff(opt->path_log),"hts-cache/new.lst"));
  476.       rename(fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-cache/old.dat"),fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-cache/new.dat"));
  477.       rename(fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-cache/old.ndx"),fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-cache/new.ndx"));
  478.       //rename(fconcat(StringBuff(opt->path_log),"hts-cache/old.lst"),fconcat(StringBuff(opt->path_log),"hts-cache/new.lst"));
  479.     }
  480.   }
  481.  
  482.   /* Interrupted mirror detected */
  483.   if (!opt->quiet) {
  484.     if (fexist(fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-in_progress.lock"))) {
  485.       /* Old cache */
  486.       if ( (fexist(fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-cache/old.dat"))) && (fexist(fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-cache/old.ndx"))) ) {
  487.         if (opt->log != NULL) {
  488.           fprintf(opt->log,"Warning!\n");
  489.           fprintf(opt->log,"An aborted mirror has been detected!\nThe current temporary cache is required for any update operation and only contains data downloaded during the last aborted session.\nThe former cache might contain more complete information; if you do not want to lose that information, you have to restore it and delete the current cache.\nThis can easily be done here by erasing the hts-cache/new.* files\n");
  490.           fprintf(opt->log,"Please restart HTTrack with --continue (-iC1) option to override this message!\n");
  491.         }
  492.         exit(0);
  493.       }
  494.     }
  495.   }
  496.     
  497.   // remplacer "macros" comme --spider
  498.   // permet de lancer httrack sans a avoir α se rappeler de syntaxes comme p0C0I0Qc32 ..
  499. #if DEBUG_STEPS
  500.   printf("Checking last macros\n");
  501. #endif
  502.   {
  503.     int i;
  504.     for(i=0;i<argc;i++) {
  505. #if DEBUG_STEPS
  506.       printf("Checking #%d:\n",argv[i]);
  507.       printf("%s\n",argv[i]);
  508. #endif
  509.       if (argv[i][0]=='-') {
  510.         if (argv[i][1]=='-') {  // --xxx
  511.           if ((strfield2(argv[i]+2,"clean")) || (strfield2(argv[i]+2,"tide"))) {  // nettoyer
  512.             strcpybuff(argv[i]+1,"");
  513.             if (fexist(fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-log.txt")))
  514.               remove(fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-log.txt"));
  515.             if (fexist(fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-err.txt")))
  516.               remove(fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-err.txt"));
  517.             if (fexist(fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_html),"index.html")))
  518.               remove(fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_html),"index.html"));
  519.             /* */
  520.             if (fexist(fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-cache/new.zip")))
  521.               remove(fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-cache/new.zip"));
  522.             if (fexist(fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-cache/old.zip")))
  523.               remove(fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-cache/old.zip"));
  524.             if (fexist(fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-cache/new.dat")))
  525.               remove(fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-cache/new.dat"));
  526.             if (fexist(fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-cache/new.ndx")))
  527.               remove(fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-cache/new.ndx"));
  528.             if (fexist(fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-cache/old.dat")))
  529.               remove(fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-cache/old.dat"));
  530.             if (fexist(fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-cache/old.ndx")))
  531.               remove(fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-cache/old.ndx"));
  532.             if (fexist(fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-cache/new.lst")))
  533.               remove(fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-cache/new.lst"));
  534.             if (fexist(fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-cache/old.lst")))
  535.               remove(fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-cache/old.lst"));
  536.             if (fexist(fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-cache/new.txt")))
  537.               remove(fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-cache/new.txt"));
  538.             if (fexist(fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-cache/old.txt")))
  539.               remove(fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-cache/old.txt"));
  540.             if (fexist(fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-cache/doit.log")))
  541.               remove(fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-cache/doit.log"));
  542.             if (fexist(fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-in_progress.lock")))
  543.               remove(fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-in_progress.lock"));
  544.             rmdir(fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-cache"));
  545.             //
  546.           } else if (strfield2(argv[i]+2,"catchurl")) {      // capture d'URL via proxy temporaire!
  547.             argv_url=1;     // forcer a passer les parametres
  548.             strcpybuff(argv[i]+1,"#P");
  549.             //
  550.           } else if (strfield2(argv[i]+2,"updatehttrack")) {
  551. #ifdef _WIN32
  552.             char s[HTS_CDLMAXSIZE + 256];
  553.             sprintf(s,"%s not available in this version",argv[i]);
  554.             HTS_PANIC_PRINTF(s);
  555.             htsmain_free();
  556.             return -1;
  557. #else
  558. #if 0
  559.             char _args[8][256];
  560.             char *args[8];
  561.             
  562.             printf("Cheking for updates...\n");
  563.             strcpybuff(_args[0],argv[0]);
  564.             strcpybuff(_args[1],"--get");
  565.             sprintf(_args[2],HTS_UPDATE_WEBSITE,0,"");
  566.             strcpybuff(_args[3],"--quickinfo");
  567.             args[0]=_args[0];
  568.             args[1]=_args[1];
  569.             args[2]=_args[2];
  570.             args[3]=_args[3];
  571.             args[4]=NULL;
  572.             if (execvp(args[0],args)==-1) {
  573.             }
  574. #endif
  575. #endif
  576.           }
  577.           //
  578.           else {
  579.             char s[HTS_CDLMAXSIZE + 256];
  580.             sprintf(s,"%s not recognized",argv[i]);
  581.             HTS_PANIC_PRINTF(s);
  582.             htsmain_free();
  583.             return -1;
  584.           }
  585.  
  586.         } 
  587.       }
  588.     }
  589.   }
  590.  
  591.   // Compter urls/jokers
  592.   /*
  593.   if (argv_url<=0) { 
  594.     int na;
  595.     argv_url=0;
  596.     for(na=1;na<argc;na++) {
  597.       if ( (strcmp(argv[na],"-P")==0) || (strcmp(argv[na],"-N")==0) || (strcmp(argv[na],"-F")==0) || (strcmp(argv[na],"-O")==0) || (strcmp(argv[na],"-V")==0) ) {
  598.         na++;    // sauter nom de proxy
  599.       } else if (!cmdl_opt(argv[na])) { 
  600.         argv_url++;   // un de plus       
  601.       } else if (strcmp(argv[na],"-h")==0) {
  602.         help(argv[0],!opt->quiet);
  603.         htsmain_free();
  604.         return 0;
  605.       } else {
  606.         if ((strchr(argv[na],'q')!=NULL))
  607.           opt->quiet=1;    // ne pas poser de questions! (nohup par exemple)
  608.         if ((strchr(argv[na],'i')!=NULL)) {  // doit.log!
  609.           argv_url=0;
  610.           na=argc;
  611.         }
  612.       }
  613.     }
  614.   }  
  615.   */
  616.  
  617.   // Ici on ajoute les arguments qui ont ΘtΘ appelΘs avant au cas o∙ on rΘcupΦre une session
  618.   // Exemple: httrack www.truc.fr -L0 puis ^C puis httrack sans URL : ajouter URL prΘcΘdente
  619.   /*
  620.   if (argv_url==0) {
  621.     //if ((fexist(fconcat(StringBuff(opt->path_log),"hts-cache/new.dat"))) && (fexist(fconcat(StringBuff(opt->path_log),"hts-cache/new.ndx")))) {  // il existe dΘja un cache prΘcΘdent.. renommer
  622.     if (fexist(fconcat(StringBuff(opt->path_log),"hts-cache/doit.log"))) {    // un cache est prΘsent
  623.       
  624.       x_argvblk=(char*) calloct(32768,1);
  625.       
  626.       if (x_argvblk!=NULL) {
  627.         FILE* fp;
  628.         int x_argc;
  629.         
  630.         //strcpybuff(x_argvblk,"httrack ");
  631.         fp=fopen(fconcat(StringBuff(opt->path_log),"hts-cache/doit.log"),"rb");
  632.         if (fp) {
  633.           linput(fp,x_argvblk+strlen(x_argvblk),8192);
  634.           fclose(fp); fp=NULL;
  635.         }
  636.         
  637.         // calculer arguments selon derniers arguments
  638.         x_argv[0]=argv[0];
  639.         x_argc=1;
  640.         {
  641.           char* p=x_argvblk;
  642.           do {
  643.             x_argv[x_argc++]=p;
  644.             //p=strstr(p," ");
  645.             // exemple de chaine: "echo \"test\"" c:\a "\$0"
  646.             p=next_token(p,1);    // prochain token
  647.             if (p) {
  648.               *p=0;    // octet nul (tableau)
  649.               p++;
  650.             }            
  651.           } while(p!=NULL);
  652.         }
  653.         // recopier arguments actuels (pointeurs uniquement)
  654.         {
  655.           int na;
  656.           for(na=1;na<argc;na++) {
  657.             if (strcmp(argv[na],"-O") != 0)    // SAUF le path!
  658.               x_argv[x_argc++]=argv[na];
  659.             else
  660.               na++;
  661.           }
  662.         }
  663.         argc=x_argc;      // nouvel argc
  664.         argv=x_argv;      // nouvel argv
  665.       }
  666.       
  667.       
  668.     }
  669.     //}
  670.   }
  671.   */
  672.   
  673.   // VΘrifier quiet
  674.   /*
  675.   { 
  676.     int na;    
  677.     for(na=1;na<argc;na++) {
  678.       if (!cmdl_opt(argv[na])) { 
  679.         if ((strcmp(argv[na],"-P")==0) || (strcmp(argv[na],"-N")==0) || (strcmp(argv[na],"-F")==0) || (strcmp(argv[na],"-O")==0) || (strcmp(argv[na],"-V")==0))
  680.           na++;    // sauter nom de proxy
  681.       } else {
  682.         if ((strchr(argv[na],'q')!=NULL) || (strchr(argv[na],'i')!=NULL))
  683.           opt->quiet=1;    // ne pas poser de questions! (nohup par exemple)
  684.       }
  685.     }
  686.   }
  687.   */
  688.  
  689.   // Pas d'URL
  690. #if DEBUG_STEPS
  691.   printf("Checking URLs\n");
  692. #endif
  693.   if (argv_url==0) {
  694.     // PrΘsence d'un cache, que faire?..
  695.     if (
  696.       ( fexist(fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-cache/new.zip")) )
  697.       ||
  698.       ( fexist(fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-cache/new.dat")) && fexist(fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-cache/new.ndx")) )
  699.       ) {  // il existe dΘja un cache prΘcΘdent.. renommer
  700.       if (fexist(fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-cache/doit.log"))) {    // un cache est prΘsent
  701.         if (x_argvblk!=NULL) {
  702.           int m;        
  703.           // Θtablir mode - mode cache: 1 (cache valide) 2 (cache α vΘrifier)
  704.           if (fexist(fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-in_progress.lock"))) {    // cache prioritaire
  705.             m=1;
  706.             recuperer=1;
  707.           } else {
  708.             m=2;
  709.           }
  710.           opt->cache=m;
  711.           
  712.           if (opt->quiet==0) {  // sinon on continue automatiquement
  713.             HT_REQUEST_START;
  714.             HT_PRINT("A cache (hts-cache/) has been found in the directory ");
  715.             HT_PRINT(StringBuff(opt->path_log));
  716.             HT_PRINT(LF);
  717.             if (m==1) {
  718.               HT_PRINT("That means that a transfer has been aborted"LF);
  719.               HT_PRINT("OK to Continue ");
  720.             } else {
  721.               HT_PRINT("That means you can update faster the remote site(s)"LF);
  722.               HT_PRINT("OK to Update ");
  723.             }
  724.             HT_PRINT("httrack "); HT_PRINT(x_argvblk); HT_PRINT("?"LF);
  725.             HT_REQUEST_END;
  726.             if (!ask_continue(opt)) { 
  727.               htsmain_free();
  728.               return 0;
  729.             }
  730.           }
  731.           
  732.         } else {
  733.           HTS_PANIC_PRINTF("Error, not enough memory");
  734.           htsmain_free();
  735.           return -1;
  736.         }
  737.       } else { // log existe pas
  738.         HTS_PANIC_PRINTF("A cache has been found, but no command line");
  739.         printf("Please launch httrack with proper parameters to reuse the cache\n");
  740.         htsmain_free();
  741.         return -1;
  742.       }
  743.       
  744.     } else {    // aucune URL dΘfinie et pas de cache
  745.       //if (argc > 1 && strcmp(argv[1], "-#h") == 0) {
  746.       //  printf("HTTrack version "HTTRACK_VERSION"%s\n", hts_get_version_info(opt));
  747.       //  exit(0);
  748.       //}
  749.       if (opt->quiet) {
  750.         help(argv[0],!opt->quiet);
  751.         htsmain_free();
  752.         return -1;
  753.       } else {
  754.         help_wizard(opt);
  755.         htsmain_free();
  756.         return -1;
  757.       }
  758.       htsmain_free();
  759.       return 0;
  760.     }
  761.   } else {   // plus de 2 paramΦtres
  762.     // un fichier log existe?
  763.     if (fexist(fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-in_progress.lock"))) {  // fichier lock?
  764.       //char s[32];
  765.       
  766.       opt->cache=1;    // cache prioritaire
  767.       if (opt->quiet==0) {
  768.         if (
  769.           ( fexist(fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-cache/new.zip")) )
  770.           ||
  771.           ( fexist(fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-cache/new.dat")) && fexist(fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-cache/new.ndx")) )
  772.           ) {
  773.           HT_REQUEST_START;
  774.           HT_PRINT("There is a lock-file in the directory ");
  775.           HT_PRINT(StringBuff(opt->path_log));
  776.           HT_PRINT(LF"That means that a mirror has not been terminated"LF);
  777.           HT_PRINT("Be sure you call httrack with proper parameters"LF);
  778.           HT_PRINT("(The cache allows you to restart faster the transfer)"LF);
  779.           HT_REQUEST_END;
  780.           if (!ask_continue(opt)) {
  781.             htsmain_free();
  782.             return 0;
  783.           }
  784.         }
  785.       }
  786.     } else if (fexist(fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_html),"index.html"))) {
  787.       //char s[32];
  788.       opt->cache=2;  // cache vient aprΦs test de validitΘ
  789.       if (opt->quiet==0) {
  790.         if (
  791.           ( fexist(fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-cache/new.zip")) )
  792.           ||
  793.           ( fexist(fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-cache/new.dat")) && fexist(fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-cache/new.ndx")) )
  794.           ) {
  795.           HT_REQUEST_START;
  796.           HT_PRINT("There is an index.html and a hts-cache folder in the directory ");
  797.           HT_PRINT(StringBuff(opt->path_log));
  798.           HT_PRINT(LF"A site may have been mirrored here, that could mean that you want to update it"LF);
  799.           HT_PRINT("Be sure parameters are ok"LF);
  800.           HT_REQUEST_END;
  801.           if (!ask_continue(opt)) {
  802.             htsmain_free();
  803.             return 0;
  804.           }
  805.         } else {
  806.           HT_REQUEST_START;
  807.           HT_PRINT("There is an index.html in the directory ");
  808.           HT_PRINT(StringBuff(opt->path_log));
  809.           HT_PRINT(" but no cache"LF);
  810.           HT_PRINT("There is an index.html in the directory, but no cache"LF);
  811.           HT_PRINT("A site may have been mirrored here, and erased.."LF);
  812.           HT_PRINT("Be sure parameters are ok"LF);
  813.           HT_REQUEST_END;
  814.           if (!ask_continue(opt)) {
  815.             htsmain_free();
  816.             return 0;
  817.           }
  818.         }
  819.       }
  820.     }
  821.   }
  822.   
  823.   
  824.   // Treat parameters
  825.   // Traiter les paramΦtres
  826. #if DEBUG_STEPS
  827.   printf("Analyze parameters\n");
  828. #endif
  829.   { 
  830.     char* com;
  831.     int na;
  832.     
  833.     for(na=1;na<argc;na++) {
  834.  
  835.       if (argv[na][0]=='"') {
  836.         char BIGSTK tempo[HTS_CDLMAXSIZE + 256];
  837.         strcpybuff(tempo,argv[na]+1);
  838.         if (tempo[strlen(tempo)-1]!='"') {
  839.           char s[HTS_CDLMAXSIZE + 256];
  840.           sprintf(s,"Missing quote in %s",argv[na]);
  841.           HTS_PANIC_PRINTF(s);
  842.           htsmain_free();
  843.           return -1;
  844.         }
  845.         tempo[strlen(tempo)-1]='\0';
  846.         strcpybuff(argv[na],tempo);
  847.       }
  848.  
  849.       if (cmdl_opt(argv[na])) { // option
  850.         com=argv[na]+1;
  851.         
  852.         while(*com) {
  853.           switch(*com) {
  854.           case ' ': case 9: case '-': case '\0': break;
  855.             //
  856.           case 'h': 
  857.             help(argv[0],0); 
  858.             htsmain_free();
  859.             return 0;   // dΘja fait normalement
  860.             //
  861.           case 'g':    // rΘcupΘrer un (ou plusieurs) fichiers isolΘs
  862.             opt->wizard=2;             // le wizard on peut plus s'en passer..
  863.             //opt->wizard=0;             // pas de wizard
  864.             opt->cache=0;              // ni de cache
  865.             opt->makeindex=0;          // ni d'index
  866.             httrack_logmode=1;            // erreurs α l'Θcran
  867.             opt->savename_type=1003;   // mettre dans le rΘpertoire courant
  868.             opt->depth=0;              // ne pas explorer la page
  869.             opt->accept_cookie=0;      // pas de cookies
  870.             opt->robots=0;             // pas de robots
  871.             break;
  872.           case 'w': opt->wizard=2;    // wizard 'soft' (ne pose pas de questions)
  873.             opt->travel=0;
  874.             opt->seeker=1;
  875.             break;
  876.           case 'W': opt->wizard=1;    // Wizard-Help (pose des questions)
  877.             opt->travel=0;
  878.             opt->seeker=1;
  879.             break;
  880.           case 'r':                      // n'est plus le recurse get bestial mais wizard itou!
  881.             if (isdigit((unsigned char)*(com+1))) {
  882.               sscanf(com+1,"%d",&opt->depth);
  883.               while(isdigit((unsigned char)*(com+1))) com++;
  884.             } else opt->depth=3;
  885.             break;
  886. /*
  887.           case 'r': opt->wizard=0;
  888.             if (isdigit((unsigned char)*(com+1))) {
  889.               sscanf(com+1,"%d",&opt->depth);
  890.               while(isdigit((unsigned char)*(com+1))) com++;
  891.             } else opt->depth=3;
  892.             break;
  893. */
  894.             //
  895.             // note: les tests opt->depth sont pour Θviter de faire
  896.             // un miroir du web (:-O) accidentelement ;-)
  897.           case 'a': /*if (opt->depth==9999) opt->depth=3;*/
  898.             opt->travel=0+(opt->travel&256); break;
  899.           case 'd': /*if (opt->depth==9999) opt->depth=3;*/
  900.             opt->travel=1+(opt->travel&256); break;
  901.           case 'l': /*if (opt->depth==9999) opt->depth=3;*/
  902.             opt->travel=2+(opt->travel&256); break;
  903.           case 'e': /*if (opt->depth==9999) opt->depth=3;*/
  904.             opt->travel=7+(opt->travel&256); break;
  905.           case 't': opt->travel|=256; break;
  906.           case 'n': opt->nearlink=1; break;
  907.           case 'x': opt->external=1; break;
  908.             //
  909.           case 'U': opt->seeker=2; break;
  910.           case 'D': opt->seeker=1; break;
  911.           case 'S': opt->seeker=0; break;
  912.           case 'B': opt->seeker=3; break;
  913.             //
  914.           case 'Y': opt->mirror_first_page=1; break;
  915.             //
  916.           case 'q': case 'i': opt->quiet=1; break;
  917.             //
  918.           case 'Q': httrack_logmode=0; break;
  919.           case 'v': httrack_logmode=1; break;
  920.           case 'f': httrack_logmode=2; if (*(com+1)=='2') httrack_logmode=3; while(isdigit((unsigned char)*(com+1))) com++; break;
  921.             //
  922.           //case 'A': opt->urlmode=1; break;
  923.           //case 'R': opt->urlmode=2; break;
  924.           case 'K': opt->urlmode=0; 
  925.             if (isdigit((unsigned char)*(com+1))) {
  926.               sscanf(com+1,"%d",&opt->urlmode);
  927.               if (opt->urlmode == 0) {  // in fact K0 ==> K2
  928.                                            // and K ==> K0
  929.                 opt->urlmode=2;
  930.               }
  931.               while(isdigit((unsigned char)*(com+1))) com++; 
  932.             }
  933.             //if (*(com+1)=='0') { opt->urlmode=2; com++; } break;
  934.             //
  935.           case 'c':
  936.             if (isdigit((unsigned char)*(com+1))) {
  937.               sscanf(com+1,"%d",&opt->maxsoc);
  938.               while(isdigit((unsigned char)*(com+1))) com++;
  939.               opt->maxsoc=max(opt->maxsoc,1);     // FORCER A 1
  940.             } else opt->maxsoc=4;
  941.             
  942.             break;
  943.             //
  944.           case 'p': sscanf(com+1,"%d",&opt->getmode); while(isdigit((unsigned char)*(com+1))) com++; break;
  945.             //        
  946.           case 'G': sscanf(com+1,LLintP,&opt->fragment); while(isdigit((unsigned char)*(com+1))) com++; break;
  947.           case 'M': sscanf(com+1,LLintP,&opt->maxsite); while(isdigit((unsigned char)*(com+1))) com++; break;
  948.           case 'm': sscanf(com+1,LLintP,&opt->maxfile_nonhtml); while(isdigit((unsigned char)*(com+1))) com++; 
  949.             if (*(com+1)==',') {
  950.               com++;
  951.               sscanf(com+1,LLintP,&opt->maxfile_html); while(isdigit((unsigned char)*(com+1))) com++;
  952.             } else opt->maxfile_html=-1;
  953.             break;
  954.             //
  955.           case 'T': sscanf(com+1,"%d",&opt->timeout); while(isdigit((unsigned char)*(com+1))) com++; break;
  956.           case 'J': sscanf(com+1,"%d",&opt->rateout); while(isdigit((unsigned char)*(com+1))) com++; break;
  957.           case 'R': sscanf(com+1,"%d",&opt->retry); while(isdigit((unsigned char)*(com+1))) com++; break;
  958.           case 'E': sscanf(com+1,"%d",&opt->maxtime); while(isdigit((unsigned char)*(com+1))) com++; break;
  959.           case 'H': sscanf(com+1,"%d",&opt->hostcontrol); while(isdigit((unsigned char)*(com+1))) com++; break;
  960.           case 'A': sscanf(com+1,"%d",&opt->maxrate); while(isdigit((unsigned char)*(com+1))) com++; break;
  961.  
  962.           case 'j':
  963.             opt->parsejava = HTSPARSE_DEFAULT;
  964.             if (isdigit((unsigned char)*(com+1))) {
  965.               sscanf(com+1,"%d",&opt->parsejava);
  966.               while(isdigit((unsigned char)*(com+1))) com++; 
  967.             }
  968.             break;
  969.             //
  970.           case 'I': opt->makeindex=1; if (*(com+1)=='0') { opt->makeindex=0; com++; } break;
  971.             //
  972.           case 'X': opt->delete_old=1; if (*(com+1)=='0') { opt->delete_old=0; com++; } break;
  973.             //
  974.           case 'b': sscanf(com+1,"%d",&opt->accept_cookie); while(isdigit((unsigned char)*(com+1))) com++; break;
  975.             //
  976.           case 'N':
  977.             if (strcmp(argv[na],"-N")==0) {    // Tout seul
  978.               if ((na+1>=argc) || (argv[na+1][0]=='-')) {  // erreur
  979.                 HTS_PANIC_PRINTF("Option N needs a number, or needs to be followed by a blank space, and a string");
  980.                 printf("Example: -N4\n");
  981.                 htsmain_free();
  982.                 return -1;
  983.               } else {
  984.                 na++;
  985.                 if (strlen(argv[na])>=127) {
  986.                   HTS_PANIC_PRINTF("Userdef structure string too long");
  987.                   htsmain_free();
  988.                   return -1;
  989.                 }
  990.                 StringCopy(opt->savename_userdef, argv[na]);
  991.                 if (StringLength(opt->savename_userdef) > 0)
  992.                   opt->savename_type = -1;    // userdef!
  993.                 else
  994.                   opt->savename_type = 0;    // -N "" : par dΘfaut
  995.               }
  996.             } else {
  997.               sscanf(com+1,"%d",&opt->savename_type); while(isdigit((unsigned char)*(com+1))) com++;
  998.             }
  999.             break;
  1000.           case 'L': 
  1001.             {
  1002.               sscanf(com+1,"%d",&opt->savename_83); 
  1003.               switch(opt->savename_83) {
  1004.               case 0:    // 8-3 (ISO9660 L1)
  1005.                 opt->savename_83=1;
  1006.                 break;
  1007.               case 1:
  1008.                 opt->savename_83=0;
  1009.                 break;
  1010.               default:    // 2 == ISO9660 (ISO9660 L2)
  1011.                 opt->savename_83=2;
  1012.                 break;
  1013.               }
  1014.               while(isdigit((unsigned char)*(com+1))) com++; 
  1015.             }
  1016.             break;
  1017.           case 's': 
  1018.             if (isdigit((unsigned char)*(com+1))) {
  1019.               sscanf(com+1,"%d",&opt->robots);
  1020.               while(isdigit((unsigned char)*(com+1))) com++;
  1021.             } else opt->robots=1;
  1022. #if DEBUG_ROBOTS
  1023.             printf("robots.txt mode set to %d\n",opt->robots);
  1024. #endif
  1025.             break;
  1026.           case 'o': sscanf(com+1,"%d",&opt->errpage); while(isdigit((unsigned char)*(com+1))) com++; break;
  1027.           case 'u': sscanf(com+1,"%d",&opt->check_type); while(isdigit((unsigned char)*(com+1))) com++; break;
  1028.             //
  1029.           case 'C': 
  1030.             if (isdigit((unsigned char)*(com+1))) {
  1031.               sscanf(com+1,"%d",&opt->cache);
  1032.               while(isdigit((unsigned char)*(com+1))) com++;
  1033.             } else opt->cache=1;
  1034.             break;
  1035.           case 'k': opt->all_in_cache=1; break;
  1036.             //
  1037.           case 'z': opt->debug=1; break;  // petit debug
  1038.           case 'Z': opt->debug=2; break;  // GROS debug
  1039.             //
  1040.           case '&': case '%': {    // deuxiΦme jeu d'options
  1041.             com++;
  1042.             switch(*com) {
  1043.             case 'M': opt->mimehtml = 1; if (*(com+1)=='0') { opt->mimehtml=0; com++; } break;
  1044.             case 'k': opt->nokeepalive = 0; if (*(com+1)=='0') { opt->nokeepalive = 1; com++; } break;
  1045.             case 'x': opt->passprivacy=1; if (*(com+1)=='0') { opt->passprivacy=0; com++; } break;   // No passwords in html files
  1046.             case 'q': opt->includequery=1; if (*(com+1)=='0') { opt->includequery=0; com++; } break;   // No passwords in html files
  1047.             case 'I': opt->kindex=1; if (isdigit((unsigned char)*(com+1))) { sscanf(com+1,"%d",&opt->kindex); while(isdigit((unsigned char)*(com+1))) com++; }
  1048.               break;    // Keyword Index
  1049.             case 'c': sscanf(com+1,"%f",&opt->maxconn); while(isdigit((unsigned char)*(com+1)) || *(com+1) == '.') com++; break;
  1050.             case 'e': sscanf(com+1,"%d",&opt->extdepth); while(isdigit((unsigned char)*(com+1))) com++; break;
  1051.             case 'B': opt->tolerant=1; if (*(com+1)=='0') { opt->tolerant=0; com++; } break;   // HTTP/1.0 notamment
  1052.             case 'h': opt->http10=1; if (*(com+1)=='0') { opt->http10=0; com++; } break;   // HTTP/1.0
  1053.             case 'z': opt->nocompression=1; if (*(com+1)=='0') { opt->nocompression=0; com++; } break;   // pas de compression
  1054.             case 'f': opt->ftp_proxy=1; if (*(com+1)=='0') { opt->ftp_proxy=0; com++; } break;   // proxy http pour ftp
  1055.             case 'P': opt->parseall=1; if (*(com+1)=='0') { opt->parseall=0; com++; } break;   // tout parser
  1056.             case 'n': opt->norecatch=1; if (*(com+1)=='0') { opt->norecatch=0; com++; } break;   // ne pas reprendre fichiers effacΘs localement
  1057.             case 's': opt->sizehack=1; if (*(com+1)=='0') { opt->sizehack=0; com++; } break;   // hack sur content-length
  1058.             case 'u': opt->urlhack=1; if (*(com+1)=='0') { opt->urlhack=0; com++; } break;   // url hack
  1059.             case 'v': opt->verbosedisplay=2; if (isdigit((unsigned char)*(com+1))) { sscanf(com+1,"%d",&opt->verbosedisplay); while(isdigit((unsigned char)*(com+1))) com++; } break;
  1060.             case 'i': opt->dir_topindex = 1; if (*(com+1)=='0') { opt->dir_topindex=0; com++; } break;
  1061.             case 'N': opt->savename_delayed = 2; if (isdigit((unsigned char)*(com+1))) { sscanf(com+1,"%d",&opt->savename_delayed); while(isdigit((unsigned char)*(com+1))) com++; } break;
  1062.             case 'D': opt->delayed_cached=1; if (*(com+1)=='0') { opt->delayed_cached=0; com++; } break;   // url hack
  1063.             case '!': opt->bypass_limits = 1; if (*(com+1)=='0') { opt->bypass_limits=0; com++; } break;
  1064. #if HTS_USEMMS
  1065.                         case 'm': sscanf(com+1,"%d",&opt->mms_maxtime); while(isdigit((unsigned char)*(com+1))) com++; break;
  1066. #endif
  1067.             case 'w':   // disable specific plugin
  1068.               if ((na+1>=argc) || (argv[na+1][0]=='-')) {
  1069.                 HTS_PANIC_PRINTF("Option %w needs to be followed by a blank space, and a module name");
  1070.                 printf("Example: -%%w htsswf\n");
  1071.                 htsmain_free();
  1072.                 return -1;
  1073.               } else{
  1074.                 na++;
  1075.                 StringCat(opt->mod_blacklist, argv[na]);
  1076.                 StringCat(opt->mod_blacklist, "\n");
  1077.               }
  1078.               break;
  1079.  
  1080.             // preserve: no footer, original links
  1081.             case 'p':
  1082.               StringClear(opt->footer);
  1083.               opt->urlmode=4;
  1084.               break;
  1085.             case 'L':    // URL list
  1086.               if ((na+1>=argc) || (argv[na+1][0]=='-')) {
  1087.                 HTS_PANIC_PRINTF("Option %L needs to be followed by a blank space, and a text filename");
  1088.                 printf("Example: -%%L \"mylist.txt\"\n");
  1089.                 htsmain_free();
  1090.                 return -1;
  1091.               } else{
  1092.                 na++;
  1093.                 if (strlen(argv[na])>=254) {
  1094.                   HTS_PANIC_PRINTF("File list string too long");
  1095.                   htsmain_free();
  1096.                   return -1;
  1097.                 }
  1098.                 StringCopy(opt->filelist,argv[na]);
  1099.               }
  1100.               break;
  1101.             case 'b':  // bind
  1102.               if ((na+1>=argc) || (argv[na+1][0]=='-')) {
  1103.                 HTS_PANIC_PRINTF("Option %b needs to be followed by a blank space, and a local hostname");
  1104.                 printf("Example: -%%b \"ip4.localhost\"\n");
  1105.                 htsmain_free();
  1106.                 return -1;
  1107.               } else{
  1108.                 na++;
  1109.                 if (strlen(argv[na])>=254) {
  1110.                   HTS_PANIC_PRINTF("Hostname string too long");
  1111.                   htsmain_free();
  1112.                   return -1;
  1113.                 }
  1114.                 StringCopy(opt->proxy.bindhost, argv[na]);
  1115.               }
  1116.               break;
  1117.             case 'S':    // Scan Rules list
  1118.               if ((na+1>=argc) || (argv[na+1][0]=='-')) {
  1119.                 HTS_PANIC_PRINTF("Option %S needs to be followed by a blank space, and a text filename");
  1120.                 printf("Example: -%%S \"myfilterlist.txt\"\n");
  1121.                 htsmain_free();
  1122.                 return -1;
  1123.               } else{
  1124.                 off_t fz;
  1125.                 na++;
  1126.                 fz = fsize(argv[na]);
  1127.                 if (fz < 0) {
  1128.                   HTS_PANIC_PRINTF("File url list could not be opened");
  1129.                   htsmain_free();
  1130.                   return -1;
  1131.                 } else {
  1132.                   FILE* fp = fopen(argv[na], "rb");
  1133.                   if (fp != NULL) {
  1134.                     int cl = (int) strlen(url);
  1135.                     ensureUrlCapacity(url, url_sz, cl + fz + 8192);
  1136.                     if (cl > 0) {  /* don't stick! (3.43) */
  1137.                       url[cl] = ' ';
  1138.                       cl++;
  1139.                     }
  1140.                     if (fread(url + cl, 1, fz, fp) != fz) {
  1141.                       HTS_PANIC_PRINTF("File url list could not be read");
  1142.                       htsmain_free();
  1143.                       return -1;
  1144.                     }
  1145.                     fclose(fp);
  1146.                     *(url + cl + fz) = '\0';
  1147.                   }
  1148.                 }
  1149.               }
  1150.               break;
  1151.             case 'A':    // assume
  1152.               if ((na+1>=argc) || (argv[na+1][0]=='-')) {
  1153.                 HTS_PANIC_PRINTF("Option %A needs to be followed by a blank space, and a filesystemtype=mimetype/mimesubtype parameters");
  1154.                 printf("Example: -%%A php3=text/html,asp=text/html\n");
  1155.                 htsmain_free();
  1156.                 return -1;
  1157.               } else{
  1158.                 na++;
  1159.                 // --assume standard
  1160.                 if (strcmp(argv[na], "standard") == 0) {
  1161.                   StringCopy(opt->mimedefs,"\n");
  1162.                   StringCat(opt->mimedefs,HTS_ASSUME_STANDARD);
  1163.                   StringCat(opt->mimedefs,"\n");
  1164.                 } else {
  1165.                   char* a;
  1166.                   //char* b = StringBuff(opt->mimedefs) + StringLength(opt->mimedefs);
  1167.                   for(a = argv[na] ; *a != '\0' ; a++) {
  1168.                     if (*a == ';') {    /* next one */
  1169.                       StringAddchar(opt->mimedefs, '\n');
  1170.                       //*b++ = '\n';
  1171.                     } else if (*a == ',' || *a == '\n' || *a == '\r' || *a == '\t') {
  1172.                       StringAddchar(opt->mimedefs, ' ');
  1173.                       //*b++ = ' ';
  1174.                     } else {
  1175.                       StringAddchar(opt->mimedefs, *a);
  1176.                       //*b++ = *a;
  1177.                     }
  1178.                   }
  1179.                   StringAddchar(opt->mimedefs, '\n');
  1180.                   //*b++ = '\n';    /* next def */
  1181.                   //*b++ = '\0';
  1182.                 }
  1183.               }
  1184.               break;
  1185.               //
  1186.             case 'l': 
  1187.               if ((na+1>=argc) || (argv[na+1][0]=='-')) {
  1188.                 HTS_PANIC_PRINTF("Option %l needs to be followed by a blank space, and an ISO language code");
  1189.                 printf("Example: -%%l \"en\"\n");
  1190.                 htsmain_free();
  1191.                 return -1;
  1192.               } else{
  1193.                 na++;
  1194.                 if (strlen(argv[na])>=62) {
  1195.                   HTS_PANIC_PRINTF("Lang list string too long");
  1196.                   htsmain_free();
  1197.                   return -1;
  1198.                 }
  1199.                 StringCopy(opt->lang_iso,argv[na]);
  1200.               }
  1201.               break;
  1202.               //
  1203.             case 'F':     // footer id
  1204.               if ((na+1>=argc) || (argv[na+1][0]=='-')) {
  1205.                 HTS_PANIC_PRINTF("Option %F needs to be followed by a blank space, and a footer string");
  1206.                 printf("Example: -%%F \"<!-- Mirrored from %%s by HTTrack Website Copier/"HTTRACK_AFF_VERSION" "HTTRACK_AFF_AUTHORS", %%s -->\"\n");
  1207.                 htsmain_free();
  1208.                 return -1;
  1209.               } else{
  1210.                 na++;
  1211.                 if (strlen(argv[na])>=254) {
  1212.                   HTS_PANIC_PRINTF("Footer string too long");
  1213.                   htsmain_free();
  1214.                   return -1;
  1215.                 }
  1216.                 StringCopy(opt->footer,argv[na]);
  1217.               }
  1218.               break;
  1219.             case 'H':                 // debug headers
  1220.               _DEBUG_HEAD=1;
  1221.               break;
  1222.             case 'O':
  1223. #ifdef _WIN32
  1224.               printf("Warning option -%%O has no effect in this system (chroot)\n");
  1225. #else
  1226.               switch_chroot=1;
  1227. #endif
  1228.               break;
  1229.             case 'U':                 // setuid
  1230.               if ((na+1>=argc) || (argv[na+1][0]=='-')) {
  1231.                 HTS_PANIC_PRINTF("Option %U needs to be followed by a blank space, and a username");
  1232.                 printf("Example: -%%U smith\n");
  1233.                 htsmain_free();
  1234.                 return -1;
  1235.               } else {
  1236.                 na++;
  1237. #ifdef _WIN32
  1238.                 printf("Warning option -%%U has no effect on this system (setuid)\n");
  1239. #else
  1240. #ifndef HTS_DO_NOT_USE_UID
  1241.                 /* Change the user id and gid */
  1242.                 {
  1243.                   struct passwd* userdef=getpwnam((const char*)argv[na]);
  1244.                   if (userdef) {    /* we'll have to switch the user id */
  1245.                     switch_gid=userdef->pw_gid;
  1246.                     switch_uid=userdef->pw_uid;
  1247.                   }
  1248.                 }
  1249. #else
  1250.                 printf("Warning option -%%U has no effect with this compiled version (setuid)\n");
  1251. #endif
  1252. #endif
  1253.               }
  1254.               break;
  1255.               
  1256.             case 'W':       // Wrapper callback
  1257.               // --wrapper check-link=obj.so:check_link
  1258.               if ((na+1>=argc) || (argv[na+1][0]=='-')) {
  1259.                 HTS_PANIC_PRINTF("Option %W needs to be followed by a blank space, and a <callback-name>=<myfile.so>:<function-name> field");
  1260.                 printf("Example: -%%W check-link=checklink.so:check\n");
  1261.                 htsmain_free();
  1262.                 return -1;
  1263.               } else {
  1264.                 char* pos;
  1265.                 na++;
  1266.                 for(pos = argv[na] ; *pos != '\0' && *pos != '=' && *pos != ',' && *pos != ':' ; pos++);
  1267.                 /* httrack --wrapper callback[,foo] */
  1268.                 if (*pos == 0 || *pos == ',' || *pos == ':') {
  1269.                   int ret;
  1270.                   char *moduleName;
  1271.                   if (*pos == ',' || *pos == ':') {
  1272.                     *pos = '\0';
  1273.                     moduleName = strdupt(argv[na]);
  1274.                     *pos = ',';   /* foce seperator to ',' */
  1275.                   } else {
  1276.                     moduleName = strdupt(argv[na]);
  1277.                   }
  1278.                   ret = plug_wrapper(opt, moduleName, argv[na]);
  1279.                   freet(moduleName);
  1280.                   if (ret == 0) {
  1281.                     char BIGSTK tmp[1024 * 2];
  1282.                     sprintf(tmp, "option %%W : unable to plug the module %s (returncode != 1)", argv[na]);
  1283.                     HTS_PANIC_PRINTF(tmp);
  1284.                     htsmain_free();
  1285.                     return -1;
  1286.                   } else if (ret == -1) {
  1287.                     char BIGSTK tmp[1024 * 2];
  1288.                     int last_errno = errno;
  1289.                     sprintf(tmp, "option %%W : unable to load the module %s: %s (check the library path ?)", argv[na], strerror(last_errno));
  1290.                     HTS_PANIC_PRINTF(tmp);
  1291.                     htsmain_free();
  1292.                     return -1;
  1293.                   }
  1294.                 }
  1295.                 /* Old style */
  1296.                 /* httrack --wrapper save-name=callback:process,string */
  1297.                 else if (*pos == '=') {
  1298.                   fprintf(stderr, "Syntax error in option %%W : the old (<3.41) API is no more supported!\n");
  1299.                   HTS_PANIC_PRINTF("Syntax error in option %W : the old (<3.41) API is no more supported!");
  1300.                   printf("Example: -%%W check-link=checklink.so:check\n");
  1301.                   htsmain_free();
  1302.                   return -1;
  1303.                 } else {
  1304.                   HTS_PANIC_PRINTF("Syntax error in option %W : this function needs to be followed by a blank space, and a module name");
  1305.                   printf("Example: -%%W check-link=checklink.so:check\n");
  1306.                   htsmain_free();
  1307.                   return -1;
  1308.                 }
  1309.               }
  1310.               break;
  1311.               
  1312.             case 'R':    // Referer
  1313.               if ((na+1>=argc) || (argv[na+1][0]=='-')) {
  1314.                 HTS_PANIC_PRINTF("Option %R needs to be followed by a blank space, and a referer URL");
  1315.                 printf("Example: -%%R \"http://www.example.com/\"\n");
  1316.                 htsmain_free();
  1317.                 return -1;
  1318.               } else{
  1319.                 na++;
  1320.                 if (strlen(argv[na])>=254) {
  1321.                   HTS_PANIC_PRINTF("Referer URL too long");
  1322.                   htsmain_free();
  1323.                   return -1;
  1324.                 }
  1325.                 StringCopy(opt->referer, argv[na]);
  1326.               }
  1327.               break;
  1328.             case 'E':    // From Email address
  1329.               if ((na+1>=argc) || (argv[na+1][0]=='-')) {
  1330.                 HTS_PANIC_PRINTF("Option %E needs to be followed by a blank space, and an email");
  1331.                 printf("Example: -%%E \"postmaster@example.com\"\n");
  1332.                 htsmain_free();
  1333.                 return -1;
  1334.               } else{
  1335.                 na++;
  1336.                 if (strlen(argv[na])>=254) {
  1337.                   HTS_PANIC_PRINTF("From email too long");
  1338.                   htsmain_free();
  1339.                   return -1;
  1340.                 }
  1341.                 StringCopy(opt->from, argv[na]);
  1342.               }
  1343.               break;
  1344.  
  1345.             default: {
  1346.               char s[HTS_CDLMAXSIZE + 256];
  1347.               sprintf(s,"invalid option %%%c\n",*com);
  1348.               HTS_PANIC_PRINTF(s);
  1349.               htsmain_free();
  1350.               return -1;
  1351.                      }
  1352.               break;
  1353.               
  1354.             }
  1355.                     }
  1356.             break;
  1357.             //
  1358.           case '@': {    // troisiΦme jeu d'options
  1359.             com++;
  1360.             switch(*com) {
  1361.             case 'i': 
  1362. #if HTS_INET6==0
  1363.               printf("Warning, option @i has no effect (v6 routines not compiled)\n");
  1364. #else 
  1365.               {
  1366.                 int res=0;
  1367.                 if (isdigit((unsigned char)*(com+1))) {
  1368.                   sscanf(com+1,"%d",&res); while(isdigit((unsigned char)*(com+1))) com++; 
  1369.                 }
  1370.                 switch(res) {
  1371.                 case 1:
  1372.                 case 4:
  1373.                   IPV6_resolver=1;
  1374.                   break;
  1375.                 case 2:
  1376.                 case 6:
  1377.                   IPV6_resolver=2;
  1378.                   break;
  1379.                 case 0:
  1380.                   IPV6_resolver=0;
  1381.                   break;
  1382.                 default:
  1383.                   printf("Unknown flag @i%d\n", res);
  1384.                   htsmain_free();
  1385.                   return -1;
  1386.                   break;
  1387.                 }
  1388.               }
  1389. #endif
  1390.               break;
  1391.               
  1392.                 default: {
  1393.                   char s[HTS_CDLMAXSIZE + 256];
  1394.                   sprintf(s,"invalid option %%%c\n",*com);
  1395.                   HTS_PANIC_PRINTF(s);
  1396.                   htsmain_free();
  1397.                   return -1;
  1398.                          }
  1399.                   break;
  1400.                   
  1401.                   //case 's': opt->sslengine=1; if (isdigit((unsigned char)*(com+1))) { sscanf(com+1,"%d",&opt->sslengine); while(isdigit((unsigned char)*(com+1))) com++; } break;
  1402.             }
  1403.                     }
  1404.             break;
  1405.             
  1406.             //
  1407.           case '#':  { // non documentΘ
  1408.             com++;
  1409.             switch(*com) {
  1410.             case 'C':   // list cache files : httrack -#C '*spid*.gif' will attempt to find the matching file
  1411.               {
  1412.                 int hasFilter = 0;
  1413.                 int found = 0;
  1414.                 char* filter=NULL;
  1415.                 cache_back cache;
  1416.                 inthash cache_hashtable=inthash_new(HTS_HASH_SIZE);
  1417.                 int backupXFR = htsMemoryFastXfr;
  1418.                 int sendb = 0;
  1419.                 if (isdigit((unsigned char)*(com+1))) {
  1420.                   sscanf(com+1,"%d",&sendb);
  1421.                   while(isdigit((unsigned char)*(com+1))) com++;
  1422.                 } else sendb=0;
  1423.                 if (!((na+1>=argc) || (argv[na+1][0]=='-'))) {
  1424.                   na++;
  1425.                   hasFilter = 1;
  1426.                   filter=argv[na];
  1427.                 }
  1428.                 htsMemoryFastXfr = 1;               /* fast load */
  1429.  
  1430.                 memset(&cache, 0, sizeof(cache_back));
  1431.                 cache.type=1;       // cache?
  1432.                 cache.log=stdout;     // log?
  1433.                 cache.errlog=stderr;  // err log?
  1434.                 cache.ptr_ant=cache.ptr_last=0;   // pointeur pour anticiper
  1435.                 cache.hashtable=(void*)cache_hashtable;      /* copy backcache hash */
  1436.                 cache.ro = 1;          /* read only */
  1437.                 if (cache.hashtable) {
  1438.                   char BIGSTK adr[HTS_URLMAXSIZE*2];
  1439.                   char BIGSTK fil[HTS_URLMAXSIZE*2];
  1440.                   char BIGSTK url[HTS_URLMAXSIZE*2];
  1441.                   char linepos[256];
  1442.                   int  pos;
  1443.                   char* cacheNdx = readfile(fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-cache/new.ndx"));
  1444.                   cache_init(&cache,opt);            /* load cache */
  1445.                   if (cacheNdx != NULL) {
  1446.                     char firstline[256];
  1447.                     char* a = cacheNdx;
  1448.                     a+=cache_brstr(a, firstline);
  1449.                     a+=cache_brstr(a, firstline);
  1450.                     while ( a != NULL ) {
  1451.                       a=strchr(a+1,'\n');     /* start of line */
  1452.                       if (a) {
  1453.                         htsblk r;
  1454.                         /* */
  1455.                         a++;
  1456.                         /* read "host/file" */
  1457.                         a+=binput(a,adr,HTS_URLMAXSIZE);
  1458.                         a+=binput(a,fil,HTS_URLMAXSIZE);
  1459.                         url[0]='\0';
  1460.                         if (!link_has_authority(adr))
  1461.                           strcatbuff(url, "http://");
  1462.                         strcatbuff(url, adr);
  1463.                         strcatbuff(url, fil);
  1464.                         /* read position */
  1465.                         a+=binput(a,linepos,200);
  1466.                         sscanf(linepos,"%d",&pos);
  1467.                         if (!hasFilter
  1468.                           ||
  1469.                           (strjoker(url, filter, NULL, NULL) != NULL)
  1470.                           ) {
  1471.                           r = cache_read_ro(opt, &cache, adr, fil, "", NULL);    // lire entrΘe cache + data
  1472.                           if (r.statuscode != -1) {    // No errors
  1473.                             found++;
  1474.                             if (!hasFilter) {
  1475.                               fprintf(stdout, "%s%s%s\r\n", 
  1476.                                 (link_has_authority(adr)) ? "" : "http://", 
  1477.                                 adr, fil);
  1478.                             } else {
  1479.                               char msg[256], cdate[256];
  1480.                               char BIGSTK sav[HTS_URLMAXSIZE*2];
  1481.                               infostatuscode(msg, r.statuscode);
  1482.                               time_gmt_rfc822(cdate);
  1483.  
  1484.                               fprintf(stdout, "HTTP/1.1 %d %s\r\n",
  1485.                                 r.statuscode,
  1486.                                 r.msg[0] ? r.msg : msg
  1487.                                 );
  1488.                               fprintf(stdout, "X-Host: %s\r\n", adr);
  1489.                               fprintf(stdout, "X-File: %s\r\n", fil);
  1490.                               fprintf(stdout, "X-URL: %s%s%s\r\n", 
  1491.                                 (link_has_authority(adr)) ? "" : "http://", 
  1492.                                 adr, fil);
  1493.                               if (url_savename(adr, fil, sav, /*former_adr*/NULL, /*former_fil*/NULL, /*referer_adr*/NULL, /*referer_fil*/NULL,
  1494.                                 /*opt*/opt, /*liens*/NULL, /*lien_tot*/0, /*sback*/NULL, /*cache*/&cache, /*hash*/NULL, /*ptr*/0, /*numero_passe*/0, /*mime_type*/NULL)!=-1) {
  1495.                                 if (fexist(sav)) {
  1496.                                   fprintf(stdout, "Content-location: %s\r\n", sav);
  1497.                                 }
  1498.                               }
  1499.                               fprintf(stdout, "Date: %s\r\n", cdate);
  1500.                               fprintf(stdout, "Server: HTTrack Website Copier/"HTTRACK_VERSION"\r\n");
  1501.                               if (r.lastmodified[0]) {
  1502.                                 fprintf(stdout, "Last-Modified: %s\r\n", r.lastmodified);
  1503.                               }
  1504.                               if (r.etag[0]) {
  1505.                                 fprintf(stdout, "Etag: %s\r\n", r.etag);
  1506.                               }
  1507.                               if (r.totalsize >= 0) {
  1508.                                 fprintf(stdout, "Content-Length: "LLintP"\r\n", r.totalsize);
  1509.                               }
  1510.                               fprintf(stdout, "X-Content-Length: "LLintP"\r\n", (r.size >= 0) ? r.size : (-r.size) );
  1511.                               if (r.contenttype >= 0) {
  1512.                                 fprintf(stdout, "Content-Type: %s\r\n", r.contenttype);
  1513.                               }
  1514.                               if (r.cdispo[0]) {
  1515.                                 fprintf(stdout, "Content-Disposition: %s\r\n", r.cdispo);
  1516.                               }
  1517.                               if (r.contentencoding[0]) {
  1518.                                 fprintf(stdout, "Content-Encoding: %s\r\n", r.contentencoding);
  1519.                               }
  1520.                               if (r.is_chunk) {
  1521.                                 fprintf(stdout, "Transfer-Encoding: chunked\r\n");
  1522.                               }
  1523. #if HTS_USEOPENSSL
  1524.                               if (r.ssl) {
  1525.                                 fprintf(stdout, "X-SSL: yes\r\n");
  1526.                               }
  1527. #endif
  1528.                               if (r.is_write) {
  1529.                                 fprintf(stdout, "X-Direct-To-Disk: yes\r\n");
  1530.                               }
  1531.                               if (r.compressed) {
  1532.                                 fprintf(stdout, "X-Compressed: yes\r\n");
  1533.                               }
  1534.                               if (r.notmodified) {
  1535.                                 fprintf(stdout, "X-Not-Modified: yes\r\n");
  1536.                               }
  1537.                               if (r.is_chunk) {
  1538.                                 fprintf(stdout, "X-Chunked: yes\r\n");
  1539.                               }
  1540.                               fprintf(stdout, "\r\n");
  1541.                               /* Send the body */
  1542.                               if (sendb && r.adr) {
  1543.                                 fprintf(stdout, "%s\r\n", r.adr);
  1544.                               }
  1545.                             }
  1546.                           }
  1547.                         }
  1548.                       }
  1549.                     }
  1550.                     freet(cacheNdx);
  1551.                   }
  1552.                 }
  1553.                 if (!found) {
  1554.                   fprintf(stderr, "No cache entry found%s%s%s\r\n",
  1555.                     (hasFilter)?" for '":"",
  1556.                     (hasFilter)?filter:"",
  1557.                     (hasFilter)?"'":""
  1558.                     );
  1559.                 }
  1560.                 htsMemoryFastXfr = backupXFR;
  1561.                 return 0;
  1562.               }
  1563.               break;
  1564.             case 'E':     // extract cache
  1565.               if (!hts_extract_meta(StringBuff(opt->path_log))) {
  1566.                 fprintf(stderr, "* error extracting meta-data\n");
  1567.                 return 1;
  1568.               }
  1569.               fprintf(stderr, "* successfully extracted meta-data\n");
  1570.               return 0;
  1571.               break;
  1572.             case 'X': 
  1573. #ifndef STRDEBUG
  1574.               fprintf(stderr, "warning: no string debugging support built, option has no effect\n");
  1575. #endif
  1576.               htsMemoryFastXfr=1; 
  1577.               if (*(com+1)=='0') { htsMemoryFastXfr=0; com++; } 
  1578.               break;
  1579.             case 'R':
  1580.               {
  1581.                 char* name;
  1582.                 uLong repaired = 0;
  1583.                 uLong repairedBytes = 0;
  1584.                 if (fexist(fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-cache/new.zip"))) {
  1585.                   name = fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-cache/new.zip");
  1586.                 } else if (fexist(fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-cache/old.zip"))) {
  1587.                   name = fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-cache/old.zip");
  1588.                 } else {
  1589.                   fprintf(stderr, "* error: no cache found in %s\n", fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-cache/new.zip"));
  1590.                   return 1;
  1591.                 }
  1592.                 fprintf(stderr, "Cache: trying to repair %s\n", name);
  1593.                 if (unzRepair(name, 
  1594.                   fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-cache/repair.zip"),
  1595.                   fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-cache/repair.tmp"),
  1596.                   &repaired, &repairedBytes
  1597.                   ) == Z_OK) {
  1598.                   unlink(name);
  1599.                   rename(fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-cache/repair.zip"), name);
  1600.                   fprintf(stderr,"Cache: %d bytes successfully recovered in %d entries\n", (int) repairedBytes, (int) repaired);
  1601.                 } else {
  1602.                   fprintf(stderr, "Cache: could not repair the cache\n");
  1603.                 }
  1604.               }
  1605.               return 0;
  1606.               break;
  1607.             case '~': /* internal lib test */
  1608.               {
  1609.                 char thisIsATestYouShouldSeeAnError[12];
  1610.                 strcpybuff(thisIsATestYouShouldSeeAnError, "0123456789012345678901234567890123456789");
  1611.                 return 0;
  1612.               }
  1613.               break;
  1614.             case 'f': opt->flush=1; break;
  1615.             case 'h':
  1616.               printf("HTTrack version "HTTRACK_VERSION"%s\n", hts_get_version_info(opt));
  1617.               return 0;
  1618.               break;
  1619.             case 'p': /* opt->aff_progress=1; deprecated */ break;
  1620.             case 'S': opt->shell=1; break;  // stdin sur un shell
  1621.             case 'K': opt->keyboard=1; break;  // vΘrifier stdin
  1622.               //
  1623.             case 'L': sscanf(com+1,"%d",&opt->maxlink); while(isdigit((unsigned char)*(com+1))) com++; break;
  1624.             case 'F': sscanf(com+1,"%d",&opt->maxfilter); while(isdigit((unsigned char)*(com+1))) com++; break;
  1625.             case 'Z': opt->makestat=1; break;
  1626.             case 'T': opt->maketrack=1; break;
  1627.             case 'u': sscanf(com+1,"%d",&opt->waittime); while(isdigit((unsigned char)*(com+1))) com++; break;
  1628.  
  1629.             /*case 'R':    // ohh ftp, catch->ftpget
  1630.               HTS_PANIC_PRINTF("Unexpected internal error with -#R command");
  1631.               htsmain_free();
  1632.               return -1;        
  1633.               break;
  1634.               */
  1635.             case 'P': {     // catchurl
  1636.               help_catchurl(StringBuff(opt->path_log));
  1637.               htsmain_free();
  1638.               return 0;
  1639.                       }
  1640.               break;
  1641.           
  1642.             case '0':   /* test #0 : filters */
  1643.               if (na+2>=argc) {
  1644.                 HTS_PANIC_PRINTF("Option #0 needs to be followed by a filter string and a string");
  1645.                 printf("Example: '-#0' '*.gif' 'foo.gif'\n");
  1646.                 htsmain_free();
  1647.                 return -1;
  1648.               } else {
  1649.                 if (strjoker(argv[na+2],argv[na+1],NULL,NULL))
  1650.                   printf("%s does match %s\n",argv[na+2],argv[na+1]);
  1651.                 else
  1652.                   printf("%s does NOT match %s\n",argv[na+2],argv[na+1]);
  1653.                 htsmain_free();
  1654.                 return 0;
  1655.               }
  1656.               break;
  1657.             case '1':   /* test #1 : fil_simplifie */
  1658.               if (na+1>=argc) {
  1659.                 HTS_PANIC_PRINTF("Option #1 needs to be followed by an URL");
  1660.                 printf("Example: '-#1' ./foo/bar/../foobar\n");
  1661.                 htsmain_free();
  1662.                 return -1;
  1663.               } else {
  1664.                 fil_simplifie(argv[na+1]);
  1665.                 printf("simplified=%s\n", argv[na+1]);
  1666.                 htsmain_free();
  1667.                 return 0;
  1668.               }
  1669.               break;
  1670.             case '2':   // mimedefs
  1671.               if (na+1>=argc) {
  1672.                 HTS_PANIC_PRINTF("Option #1 needs to be followed by an URL");
  1673.                 printf("Example: '-#2' /foo/bar.php\n");
  1674.                 htsmain_free();
  1675.                 return -1;
  1676.               } else {
  1677.                 char mime[256];
  1678.                 // initialiser mimedefs
  1679.                 //get_userhttptype(opt,1,opt->mimedefs,NULL);
  1680.                 // check
  1681.                 mime[0] = '\0';
  1682.                 get_httptype(opt, mime, argv[na+1], 0);
  1683.                 if (mime[0] != '\0') {
  1684.                   char ext[256];
  1685.                   printf("%s is '%s'\n", argv[na+1], mime);
  1686.                   ext[0] = '\0';
  1687.                   give_mimext(ext, mime);
  1688.                   if (ext[0]) {
  1689.                     printf("and its local type is '.%s'\n", ext);
  1690.                   }
  1691.                 } else {
  1692.                   printf("%s is of an unknown MIME type\n", argv[na+1]);
  1693.                 }
  1694.                 htsmain_free();
  1695.                 return 0;
  1696.               }
  1697.               break;
  1698.             case '!':
  1699.               if (na+1>=argc) {
  1700.                 HTS_PANIC_PRINTF("Option #! needs to be followed by a commandline");
  1701.                 printf("Example: '-#!' 'echo hello'\n");
  1702.                 htsmain_free();
  1703.                 return -1;
  1704.               } else {
  1705.                 system(argv[na+1]);
  1706.               }
  1707.               break;
  1708.             case 'd':
  1709.               opt->parsedebug = 1;
  1710.               break;
  1711.  
  1712.             /* autotest */
  1713.             case 't':     /* not yet implemented */
  1714.               fprintf(stderr, "** AUTOCHECK OK\n");
  1715.               exit(0);
  1716.               break;
  1717.  
  1718.             default: printf("Internal option %c not recognized\n",*com); break;
  1719.             }
  1720.                      }
  1721.             break; 
  1722.           case 'O':    // output path
  1723.                         while(isdigit(com[1])) {
  1724.                             com++;
  1725.                         }
  1726.             na++;     // sauter, dΘja traitΘ
  1727.             break;
  1728.           case 'P':    // proxy
  1729.             if ((na+1>=argc) || (argv[na+1][0]=='-')) {
  1730.               HTS_PANIC_PRINTF("Option P needs to be followed by a blank space, and a proxy proxy:port or user:id@proxy:port");
  1731.               printf("Example: -P proxy.myhost.com:8080\n");
  1732.               htsmain_free();
  1733.               return -1;
  1734.             } else {
  1735.               char* a;
  1736.               na++;
  1737.               opt->proxy.active=1;
  1738.               // Rechercher MAIS en partant de la fin α cause de user:pass@proxy:port
  1739.               a = argv[na] + strlen(argv[na]) -1;
  1740.               // a=strstr(argv[na],":");  // port
  1741.               while( (a > argv[na]) && (*a != ':') && (*a != '@') ) a--;
  1742.               if (*a == ':') {  // un port est prΘsent, <proxy>:port
  1743.                 sscanf(a+1,"%d",&opt->proxy.port);
  1744.                 StringCopyN(opt->proxy.name,argv[na],(int) (a - argv[na]));
  1745.               } else {  // <proxy>
  1746.                 opt->proxy.port=8080;
  1747.                 StringCopy(opt->proxy.name,argv[na]);
  1748.               }
  1749.             }
  1750.             break;
  1751.           case 'F':    // user-agent field
  1752.             if ((na+1>=argc) || (argv[na+1][0]=='-')) {
  1753.               HTS_PANIC_PRINTF("Option F needs to be followed by a blank space, and a user-agent name");
  1754.               printf("Example: -F \"my_user_agent/1.0\"\n");
  1755.               htsmain_free();
  1756.               return -1;
  1757.             } else{
  1758.               na++;
  1759.               if (strlen(argv[na])>=126) {
  1760.                 HTS_PANIC_PRINTF("User-agent length too long");
  1761.                 htsmain_free();
  1762.                 return -1;
  1763.               }
  1764.               StringCopy(opt->user_agent,argv[na]);
  1765.               if (StringNotEmpty(opt->user_agent))
  1766.                 opt->user_agent_send=1;
  1767.               else
  1768.                 opt->user_agent_send=0;    // -F "" dΘsactive l'option
  1769.             }
  1770.             break;
  1771.             //
  1772.           case 'V':    // execute command
  1773.             if ((na+1>=argc) || (argv[na+1][0]=='-')) {
  1774.               HTS_PANIC_PRINTF("Option V needs to be followed by a system-command string");
  1775.               printf("Example: -V \"tar uvf some.tar \\$0\"\n");
  1776.               htsmain_free();
  1777.               return -1;
  1778.             } else{
  1779.               na++;
  1780.               if (strlen(argv[na])>=2048) {
  1781.                 HTS_PANIC_PRINTF("System-command length too long");
  1782.                 htsmain_free();
  1783.                 return -1;
  1784.               }
  1785.               StringCopy(opt->sys_com,argv[na]);
  1786.               if (StringNotEmpty(opt->sys_com))
  1787.                 opt->sys_com_exec=1;
  1788.               else
  1789.                 opt->sys_com_exec=0;    // -V "" dΘsactive l'option
  1790.             }
  1791.             break;
  1792.             //
  1793.           default: {
  1794.             char s[HTS_CDLMAXSIZE + 256];
  1795.             sprintf(s,"invalid option %c\n",*com);
  1796.             HTS_PANIC_PRINTF(s);
  1797.             htsmain_free();
  1798.             return -1;
  1799.                    }
  1800.             break;
  1801.           }  // switch
  1802.           com++;    
  1803.         }  // while
  1804.         
  1805.       }  else {  // URL/filters
  1806.                 char catbuff[CATBUFF_SIZE];
  1807.         char BIGSTK tempo[CATBUFF_SIZE];
  1808.         const int urlSize = (int) strlen(argv[na]);
  1809.         const int capa = (int) ( strlen(url) + urlSize + 32 );
  1810.         assertf(urlSize < HTS_URLMAXSIZE);
  1811.         if (urlSize < HTS_URLMAXSIZE) {
  1812.             ensureUrlCapacity(url, url_sz, capa);
  1813.             if (strnotempty(url)) strcatbuff(url," ");  // espace de sΘparation
  1814.             strcpybuff(tempo,unescape_http_unharm(catbuff,argv[na],1));
  1815.             escape_spc_url(tempo);
  1816.             strcatbuff(url,tempo);
  1817.         }
  1818.       }  // if argv=- etc. 
  1819.       
  1820.     }  // for
  1821.   }
  1822.   
  1823. #if BDEBUG==3  
  1824.   printf("URLs/filters=%s\n",url);
  1825. #endif
  1826.  
  1827. #if DEBUG_STEPS
  1828.   printf("Analyzing parameters done\n");
  1829. #endif
  1830.  
  1831.  
  1832. #ifdef _WIN32
  1833. #else
  1834. #ifndef HTS_DO_NOT_USE_UID
  1835.   /* Chroot - xxc */
  1836.   if (switch_chroot) {
  1837.     uid_t userid=getuid();
  1838.     //struct passwd* userdef=getpwuid(userid);
  1839.     //if (userdef) {
  1840.     if (!userid) {
  1841.       //if (strcmp(userdef->pw_name,"root")==0) {
  1842.       char BIGSTK rpath[1024];
  1843.       //printf("html=%s log=%s\n",StringBuff(opt->path_html),StringBuff(opt->path_log));    // xxc
  1844.       if ((StringBuff(opt->path_html)[0]) && (StringBuff(opt->path_log)[0])) {
  1845.         const char *a=StringBuff(opt->path_html),*b=StringBuff(opt->path_log),*c=NULL,*d=NULL;
  1846.         c=a; d=b;
  1847.         while ((*a) && (*a == *b)) {
  1848.           if (*a=='/') { c=a; d=b; }
  1849.           a++;
  1850.           b++;
  1851.         }
  1852.  
  1853.         rpath[0]='\0';
  1854.         if (c != StringBuff(opt->path_html)) {
  1855.           if (StringBuff(opt->path_html)[0]!='/')
  1856.             strcatbuff(rpath,"./");
  1857.           strncatbuff(rpath,StringBuff(opt->path_html),(int) (c - StringBuff(opt->path_html)));
  1858.         }
  1859.         StringCopyOverlapped(opt->path_html, c);
  1860.         StringCopyOverlapped(opt->path_log, d);
  1861.       } else {
  1862.         strcpybuff(rpath,"./");
  1863.         StringCopy(opt->path_html,"/");
  1864.         StringCopy(opt->path_log,"/");
  1865.       }
  1866.       if (rpath[0]) {
  1867.         printf("[changing root path to %s (path_data=%s,path_log=%s)]\n",rpath,StringBuff(opt->path_html),StringBuff(opt->path_log));
  1868.         if (chroot(rpath)) {
  1869.           printf("ERROR! Can not chroot to %s!\n",rpath);
  1870.           return -1;
  1871.         }
  1872.         if (chdir("/")) {     /* new root */
  1873.           printf("ERROR! Can not chdir to %s!\n",rpath);
  1874.           return -1;
  1875.         }
  1876.       } else
  1877.         printf("WARNING: chroot not possible with these paths\n");
  1878.     }
  1879.     //}
  1880.   }
  1881.  
  1882.   /* Setuid */
  1883.   if (switch_uid>=0) {
  1884.     printf("[setting user/group to %d/%d]\n",switch_uid,switch_gid);
  1885.     if (setgid(switch_gid))
  1886.       printf("WARNING! Can not setgid to %d!\n",switch_gid);
  1887.     if (setuid(switch_uid))
  1888.       printf("WARNING! Can not setuid to %d!\n",switch_uid);
  1889.   }
  1890.  
  1891.   /* Final check */
  1892.   {
  1893.     uid_t userid=getuid();
  1894.     if (!userid) {              /* running as r00t */
  1895.       printf("WARNING! You are running this program as root!\n");
  1896.       printf("It might be a good idea to use the -%%U option to change the userid:\n");
  1897.       printf("Example: -%%U smith\n\n");
  1898.     }
  1899.   }
  1900. #endif
  1901. #endif
  1902.   
  1903.   //printf("WARNING! This is *only* a beta-release of HTTrack\n");
  1904.   io_flush;
  1905.   
  1906. #if DEBUG_STEPS
  1907.   printf("Cache & log settings\n");
  1908. #endif
  1909.   
  1910.   // on utilise le cache..
  1911.   // en cas de prΘsence des deux versions, garder la version la plus avancΘe,
  1912.   // cad la version contenant le plus de fichiers  
  1913.   if (opt->cache) {
  1914.     if (fexist(fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-in_progress.lock"))) {   // problemes..
  1915.       if ( fexist(fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-cache/new.dat")) ) { 
  1916.         if ( fexist(fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-cache/old.zip")) ) {
  1917.           if (fsize(fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-cache/new.zip"))<32768) {
  1918.             if (fsize(fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-cache/old.zip"))>65536) {
  1919.               if (fsize(fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-cache/old.zip")) > fsize(fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-cache/new.zip"))) {
  1920.                 remove(fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-cache/new.zip"));
  1921.                 rename(fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-cache/old.zip"), fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-cache/new.zip"));
  1922.               }
  1923.             }
  1924.           }
  1925.         }
  1926.       }
  1927.       else if (fexist(fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-cache/new.dat")) && fexist(fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-cache/new.ndx"))) { 
  1928.         if (fexist(fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-cache/old.dat")) && fexist(fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-cache/old.ndx"))) {
  1929.           // switcher si new<32Ko et old>65Ko (tailles arbitraires) ?
  1930.           // ce cas est peut Ωtre une erreur ou un crash d'un miroir ancien, prendre
  1931.           // alors l'ancien cache
  1932.           if (fsize(fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-cache/new.dat"))<32768) {
  1933.             if (fsize(fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-cache/old.dat"))>65536) {
  1934.               if (fsize(fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-cache/old.dat")) > fsize(fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-cache/new.dat"))) {
  1935.                 remove(fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-cache/new.dat"));
  1936.                 remove(fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-cache/new.ndx"));
  1937.                 rename(fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-cache/old.dat"),fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-cache/new.dat"));
  1938.                 rename(fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-cache/old.ndx"),fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-cache/new.ndx"));  
  1939.                 //} else {  // ne rien faire
  1940.                 //  remove("hts-cache/old.dat");
  1941.                 //  remove("hts-cache/old.ndx");
  1942.               }
  1943.             }
  1944.           }
  1945.         }
  1946.       }
  1947.     }
  1948.   }
  1949.  
  1950.   // DΘbuggage des en tΩtes
  1951.   if (_DEBUG_HEAD) {
  1952.     ioinfo=fopen(fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-ioinfo.txt"),"wb");
  1953.   }
  1954.   
  1955.   {
  1956.     char n_lock[256];
  1957.     // on peut pas avoir un affichage ET un fichier log
  1958.     // ca sera pour la version 2
  1959.     if (httrack_logmode==1) {
  1960.       opt->log=stdout;
  1961.       opt->errlog=stderr;
  1962.     } else if (httrack_logmode>=2) {
  1963.       // deux fichiers log
  1964.       structcheck(StringBuff(opt->path_log));
  1965.       if (fexist(fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-log.txt")))
  1966.         remove(fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-log.txt"));
  1967.       if (fexist(fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-err.txt")))
  1968.         remove(fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-err.txt"));
  1969.  
  1970.       /* Check FS directory structure created */
  1971.       structcheck(StringBuff(opt->path_log));
  1972.  
  1973.       opt->log=fopen(fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-log.txt"),"w");
  1974.       if (httrack_logmode==2)
  1975.         opt->errlog=fopen(fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-err.txt"),"w");
  1976.       else
  1977.         opt->errlog=opt->log;
  1978.       if (opt->log==NULL) {
  1979.         char s[HTS_CDLMAXSIZE + 256];
  1980.         sprintf(s,"Unable to create log file %s",fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-log.txt"));
  1981.         HTS_PANIC_PRINTF(s);
  1982.         htsmain_free();
  1983.         return -1;
  1984.       } else if (opt->errlog==NULL) {
  1985.         char s[HTS_CDLMAXSIZE + 256];
  1986.         sprintf(s,"Unable to create log file %s",fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-err.txt"));
  1987.         HTS_PANIC_PRINTF(s);
  1988.         htsmain_free();
  1989.         return -1;
  1990.       }
  1991.  
  1992.     } else {
  1993.       opt->log=NULL;
  1994.       opt->errlog=NULL;
  1995.     }
  1996.     
  1997.     // un petit lock-file pour indiquer un miroir en cours, ainsi qu'un Θventuel fichier log
  1998.     {
  1999.       FILE* fp=NULL;
  2000.       //int n=0;
  2001.       char t[256];
  2002.       time_local_rfc822(t);    // faut bien que ca serve quelque part l'heure RFC1945 arf'
  2003.       
  2004.       /* readme for information purpose */
  2005.       {
  2006.         FILE* fp=fopen(fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-cache/readme.txt"),"wb");
  2007.         if (fp) {
  2008.           fprintf(fp,"What's in this folder?"LF);
  2009.           fprintf(fp,""LF);
  2010.           fprintf(fp,"This folder (hts-cache) has been generated by WinHTTrack "HTTRACK_VERSION"%s"LF, hts_get_version_info(opt));
  2011.           fprintf(fp,"and is used for updating this website."LF);
  2012.           fprintf(fp,"(The HTML website structure is stored here to allow fast updates)"LF""LF);
  2013.           fprintf(fp,"DO NOT delete this folder unless you do not want to update the mirror in the future!!"LF);
  2014.           fprintf(fp,"(you can safely delete old.zip and old.lst files, however)"LF);
  2015.           fprintf(fp,""LF);
  2016.           fprintf(fp,HTS_LOG_SECURITY_WARNING);
  2017.           fclose(fp);
  2018.         }
  2019.       }
  2020.  
  2021.       sprintf(n_lock,fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-in_progress.lock"));
  2022.       //sprintf(n_lock,fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-in_progress.lock"),n);
  2023.       /*do {
  2024.         if (!n)
  2025.           sprintf(n_lock,fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-in_progress.lock"),n);
  2026.         else
  2027.           sprintf(n_lock,fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-in_progress%d.lock"),n);
  2028.         n++;
  2029.       } while((fexist(n_lock)) && opt->quiet);      
  2030.       if (fexist(n_lock)) {
  2031.         if (!recuperer) {
  2032.           remove(n_lock);
  2033.         }
  2034.       }*/
  2035.  
  2036.       // vΘrifier existence de la structure
  2037.       structcheck(fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_html), "/"));
  2038.       structcheck(fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log), "/"));
  2039.      
  2040.       // reprise/update
  2041.       if (opt->cache) {
  2042.         FILE* fp;
  2043.         int i;
  2044. #ifdef _WIN32
  2045.         mkdir(fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-cache"));
  2046. #else
  2047.         mkdir(fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-cache"),HTS_PROTECT_FOLDER);
  2048. #endif
  2049.         fp=fopen(fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log),"hts-cache/doit.log"),"wb");
  2050.         if (fp) {
  2051.           for(i=0+1;i<argc;i++) {
  2052.             if ( ((strchr(argv[i],' ')!=NULL) || (strchr(argv[i],'"')!=NULL) || (strchr(argv[i],'\\')!=NULL)) && (argv[i][0]!='"')  ) {
  2053.               int j;
  2054.               fprintf(fp,"\"");
  2055.               for(j=0;j<(int) strlen(argv[i]);j++) {
  2056.                 if (argv[i][j]==34)
  2057.                   fprintf(fp,"\\\"");
  2058.                 else if (argv[i][j]=='\\')
  2059.                   fprintf(fp,"\\\\");
  2060.                 else
  2061.                   fprintf(fp,"%c",argv[i][j]);
  2062.               }
  2063.               fprintf(fp,"\"");
  2064.             } else if (strnotempty(argv[i])==0) {   // ""
  2065.               fprintf(fp,"\"\"");
  2066.             } else {   // non critique
  2067.               fprintf(fp,"%s",argv[i]);
  2068.             }
  2069.             if (i<argc-1)
  2070.               fprintf(fp," ");
  2071.           }
  2072.           fprintf(fp,LF);
  2073.           fprintf(fp,"File generated automatically on %s, do NOT edit"LF,t);
  2074.           fprintf(fp,LF);
  2075.           fprintf(fp,"To update a mirror, just launch httrack without any parameters"LF);
  2076.           fprintf(fp,"The existing cache will be used (and modified)"LF);
  2077.           fprintf(fp,"To have other options, retype all parameters and launch HTTrack"LF);
  2078.           fprintf(fp,"To continue an interrupted mirror, just launch httrack without any parameters"LF);
  2079.           fprintf(fp,LF);
  2080.           fclose(fp); fp=NULL;
  2081.         //} else if (opt->debug>1) {
  2082.         //  printf("! FileOpen error, \"%s\"\n",strerror(errno));
  2083.         }
  2084.       }
  2085.       
  2086.       // petit message dans le lock
  2087.       if ( (fp=fopen(n_lock,"wb"))!=NULL) {
  2088.         int i;
  2089.         fprintf(fp,"Mirror in progress since %s .. please wait!"LF,t);
  2090.         for(i=0;i<argc;i++) {
  2091.           if (strchr(argv[i],' ')==NULL)
  2092.             fprintf(fp,"%s ",argv[i]);
  2093.           else    // entre ""
  2094.             fprintf(fp,"\"%s\" ",argv[i]);
  2095.         }
  2096.         fprintf(fp,LF);
  2097.         fprintf(fp, "To pause the engine: create an empty file named 'hts-stop.lock'"LF);
  2098. #if USE_BEGINTHREAD
  2099.                 fprintf(fp, "PID=%d\n", (int)getpid());
  2100. #ifndef _WIN32
  2101.                 fprintf(fp, "UID=%d\n", (int)getuid());
  2102.                 fprintf(fp, "GID=%d\n", (int)getuid());
  2103. #endif
  2104.                 fprintf(fp, "START=%d\n", (int)time(NULL));
  2105. #endif
  2106.         fclose(fp); fp=NULL;
  2107.       }
  2108.       
  2109.       // fichier log        
  2110.       if (opt->log)     {
  2111.         int i;
  2112.         fprintf(opt->log,"HTTrack"HTTRACK_VERSION"%s launched on %s at %s"LF, 
  2113.           hts_get_version_info(opt),
  2114.           t, url);
  2115.         fprintf(opt->log,"(");
  2116.         for(i=0;i<argc;i++) {
  2117.           if (strchr(argv[i],' ') == NULL || strchr(argv[i],'\"') != NULL)
  2118.             fprintf(opt->log,"%s ",argv[i]);
  2119.           else    // entre "" (si espace(s) et pas dΘja de ")
  2120.             fprintf(opt->log,"\"%s\" ",argv[i]);
  2121.         }
  2122.         fprintf(opt->log,")"LF);
  2123.         fprintf(opt->log,LF);
  2124.         fprintf(opt->log,"Information, Warnings and Errors reported for this mirror:"LF);
  2125.         fprintf(opt->log,HTS_LOG_SECURITY_WARNING );
  2126.         fprintf(opt->log,LF);
  2127.       }
  2128.  
  2129.       if (httrack_logmode) {
  2130.         printf("Mirror launched on %s by HTTrack Website Copier/"HTTRACK_VERSION"%s "HTTRACK_AFF_AUTHORS""LF,t,hts_get_version_info(opt));
  2131.         if (opt->wizard==0) {
  2132.           printf("mirroring %s with %d levels, %d sockets,t=%d,s=%d,logm=%d,lnk=%d,mdg=%d\n",url,opt->depth,opt->maxsoc,opt->travel,opt->seeker,httrack_logmode,opt->urlmode,opt->getmode);
  2133.         } else {    // the magic wizard
  2134.           printf("mirroring %s with the wizard help..\n",url);
  2135.         }
  2136.       }
  2137.     }
  2138.     
  2139.     io_flush;
  2140.  
  2141.     /* Enforce limits to avoid bandwith abuse. The bypass_limits should only be used by administrators and experts. */
  2142.     if (!opt->bypass_limits) {
  2143.       if (opt->maxsoc <= 0 || opt->maxsoc > 4) {
  2144.         opt->maxsoc = 4;
  2145.         if (opt->log != NULL) {
  2146.           HTS_LOG(opt,LOG_WARNING); fprintf(opt->log,"* security warning: maximum number of simultaneous connections limited to %d to avoid server overload"LF, (int)opt->maxsoc);
  2147.         }
  2148.       }
  2149.       if (opt->maxrate <= 0 || opt->maxrate > 100000) {
  2150.         opt->maxrate = 100000;
  2151.         if (opt->log != NULL) {
  2152.           HTS_LOG(opt,LOG_WARNING); fprintf(opt->log,"* security warning: maximum bandwidth limited to %d to avoid server overload"LF, (int)opt->maxrate);
  2153.         }
  2154.       }
  2155.       if (opt->maxconn <= 0 || opt->maxconn > 5.0) {
  2156.         opt->maxconn = 5.0;
  2157.         if (opt->log != NULL) {
  2158.           HTS_LOG(opt,LOG_WARNING); fprintf(opt->log,"* security warning: maximum number of connections per second limited to %f to avoid server overload"LF, (float)opt->maxconn);
  2159.         }
  2160.       }
  2161.     } else {
  2162.       if (opt->log != NULL) {
  2163.         HTS_LOG(opt,LOG_WARNING); fprintf(opt->log,"* security warning: !!! BYPASSING SECURITY LIMITS - MONITOR THIS SESSION WITH EXTREME CARE !!!"LF);
  2164.       }
  2165.     }
  2166.  
  2167.   /* Info for wrappers */
  2168.   if ( (opt->debug>0) && (opt->log!=NULL) ) {
  2169.     HTS_LOG(opt,LOG_INFO); fprintf(opt->log,"engine: init"LF);
  2170.   }
  2171.  
  2172.   /* Init external */
  2173.   RUN_CALLBACK_NOARG(opt, init);
  2174.  
  2175.   // dΘtourner SIGHUP etc.
  2176. #if DEBUG_STEPS
  2177.   printf("Launching the mirror\n");
  2178. #endif
  2179.  
  2180.     // Lancement du miroir
  2181.     // ------------------------------------------------------------
  2182.     if (httpmirror(url, opt)==0) {
  2183.       printf("Error during operation (see log file), site has not been successfully mirrored\n");
  2184.     } else {
  2185.       if  (opt->shell) {
  2186.         HTT_REQUEST_START;
  2187.         HT_PRINT("TRANSFER DONE"LF);
  2188.         HTT_REQUEST_END
  2189.       } else {
  2190.         printf("Done.\n");
  2191.       }
  2192.     }
  2193.     // ------------------------------------------------------------
  2194.  
  2195.     //
  2196.     // Build top index
  2197.     if (opt->dir_topindex) {
  2198.       char BIGSTK rpath[1024*2];
  2199.       char* a;
  2200.       strcpybuff(rpath,StringBuff(opt->path_html));
  2201.       if (rpath[0]) {
  2202.         if (rpath[strlen(rpath)-1]=='/')
  2203.           rpath[strlen(rpath)-1]='\0';
  2204.       }
  2205.       a=strrchr(rpath,'/');
  2206.       if (a) {
  2207.         *a='\0';
  2208.         hts_buildtopindex(opt,rpath,StringBuff(opt->path_bin));
  2209.         if (opt->log) {
  2210.           HTS_LOG(opt,LOG_INFO); fprintf(opt->log,"Top index rebuilt (done)"LF);
  2211.         }
  2212.       }
  2213.     }
  2214.  
  2215.     if (opt->state.exit_xh ==1) {
  2216.       if (opt->log) {
  2217.         fprintf(opt->log,"* * MIRROR ABORTED! * *\nThe current temporary cache is required for any update operation and only contains data downloaded during the present aborted session.\nThe former cache might contain more complete information; if you do not want to lose that information, you have to restore it and delete the current cache.\nThis can easily be done here by erasing the hts-cache/new.* files]\n");
  2218.       }
  2219.     }
  2220.  
  2221.     /* Not or cleanly interrupted; erase hts-cache/ref temporary directory */
  2222.     if (opt->state.exit_xh == 0) {
  2223.       // erase ref files if not interrupted
  2224.       DIR *dir;
  2225.       struct dirent *entry;
  2226.       for(dir = opendir(fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log), CACHE_REFNAME)) 
  2227.         ; dir != NULL && ( entry = readdir(dir) ) != NULL 
  2228.         ; )
  2229.       {
  2230.         if (entry->d_name[0] != '\0' && entry->d_name[0] != '.') {
  2231.           char *f = OPT_GET_BUFF(opt);
  2232.           sprintf(f, "%s/%s", CACHE_REFNAME, entry->d_name);
  2233.           (void)unlink(fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log), f));
  2234.         }
  2235.       }
  2236.       if (dir != NULL) {
  2237.         (void) closedir(dir);
  2238.       }
  2239.       (void)rmdir(fconcat(OPT_GET_BUFF(opt), StringBuff(opt->path_log), CACHE_REFNAME));
  2240.     }
  2241.  
  2242.     /* Info for wrappers */
  2243.     if ( (opt->debug>0) && (opt->log!=NULL) ) {
  2244.       HTS_LOG(opt,LOG_INFO); fprintf(opt->log,"engine: free"LF);
  2245.     }
  2246.  
  2247.     /* UnInit */
  2248.     RUN_CALLBACK_NOARG(opt, uninit);
  2249.  
  2250.     if (httrack_logmode!=1) {
  2251.       if (opt->errlog == opt->log) opt->errlog=NULL;
  2252.       if (opt->log) { fclose(opt->log); opt->log=NULL; }
  2253.       if (opt->errlog) { fclose(opt->errlog); opt->errlog=NULL; }
  2254.     }  
  2255.  
  2256.     // DΘbuggage des en tΩtes
  2257.     if (_DEBUG_HEAD) {
  2258.       if (ioinfo) {
  2259.         fclose(ioinfo);
  2260.       }
  2261.     }
  2262.  
  2263.     // supprimer lock
  2264.     remove(n_lock);
  2265.   }
  2266.  
  2267.   if (x_argvblk)
  2268.     freet(x_argvblk);
  2269.   if (x_argv)
  2270.     freet(x_argv);
  2271.   if (url)
  2272.     freet(url);
  2273.  
  2274. #ifdef HTS_TRACE_MALLOC
  2275.   hts_freeall();
  2276. #endif
  2277.  
  2278.   printf("Thanks for using HTTrack!\n");
  2279.   io_flush;
  2280.   htsmain_free();
  2281.   return 0;    // OK
  2282. }
  2283.  
  2284.  
  2285. // main() subroutines
  2286.  
  2287. // vΘrifier chemin path
  2288. int check_path(String* s, char* defaultname) {
  2289.   int i;
  2290.   int return_value=0;
  2291.  
  2292.   // Replace name: ~/mywebsites/# -> /home/foo/mywebsites/#
  2293.   expand_home(s);
  2294.   for(i = 0 ; i < (int) StringLength(*s) ; i++)    // conversion \ -> /
  2295.     if (StringSub(*s, i) == '\\')
  2296.       StringSubRW(*s, i) = '/';
  2297.   
  2298.   // remove ending /
  2299.   if (StringNotEmpty(*s) && StringRight(*s, 1) == '/')
  2300.     StringPopRight(*s);
  2301.  
  2302.    // Replace name: /home/foo/mywebsites/# -> /home/foo/mywebsites/wonderfulsite
  2303.   if (StringNotEmpty(*s)) {
  2304.     if (StringRight(*s, 1) == '#') {
  2305.       if (strnotempty((defaultname?defaultname:""))) {
  2306.         char* a = strchr(defaultname,'#');      // we never know..
  2307.         if (a)
  2308.           *a='\0';
  2309.         StringPopRight(*s);
  2310.         StringCat(*s, defaultname);
  2311.       } else {
  2312.         StringClear(*s); // Clear path (no name/default url given)
  2313.       }
  2314.       return_value=1;     // expanded
  2315.     }
  2316.   }
  2317.  
  2318.   // ending /
  2319.   if (StringNotEmpty(*s) && StringRight(*s, 1) != '/')    // ajouter slash α la fin
  2320.     StringCat(*s, "/");
  2321.  
  2322.   return return_value;
  2323. }
  2324.  
  2325. // dΘtermine si l'argument est une option
  2326. int cmdl_opt(char* s) {
  2327.   if (s[0]=='-') {  // c'est peut Ωtre une option
  2328.     if (strchr(s,'.')!=NULL && strchr(s,'%')==NULL)
  2329.       return 0;    // sans doute un -www.truc.fr (note: -www n'est pas compris)
  2330.     else if (strchr(s,'/')!=NULL)
  2331.       return 0;    // idem, -*cgi-bin/
  2332.     else if (strchr(s,'*')!=NULL)
  2333.       return 0;    // joker, idem
  2334.     else
  2335.       return 1;
  2336.   } else return 0;
  2337. }
  2338.  
  2339.